1 /*
2  * Copyright (C) 2017 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 <hardware/hardware.h>
20 #include <hardware/vibrator.h>
21 #include <log/log.h>
22 #include <stdio.h>
23 #include <utils/Trace.h>
24 
25 #include <cinttypes>
26 #include <cmath>
27 #include <fstream>
28 #include <iostream>
29 #include <map>
30 #include <sstream>
31 
32 #ifndef ARRAY_SIZE
33 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
34 #endif
35 
36 #define PROC_SND_PCM "/proc/asound/pcm"
37 #define HAPTIC_PCM_DEVICE_SYMBOL "haptic nohost playback"
38 
39 namespace aidl {
40 namespace android {
41 namespace hardware {
42 namespace vibrator {
43 
44 static constexpr uint32_t BASE_CONTINUOUS_EFFECT_OFFSET = 32768;
45 
46 static constexpr uint32_t WAVEFORM_EFFECT_0_20_LEVEL = 0;
47 static constexpr uint32_t WAVEFORM_EFFECT_1_00_LEVEL = 4;
48 static constexpr uint32_t WAVEFORM_EFFECT_LEVEL_MINIMUM = 4;
49 
50 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_SILENCE_MS = 100;
51 
52 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0;
53 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_THRESHOLD_MS = 50;
54 static constexpr uint32_t WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3 + BASE_CONTINUOUS_EFFECT_OFFSET;
55 
56 static constexpr uint32_t WAVEFORM_CLICK_INDEX = 2;
57 static constexpr uint32_t WAVEFORM_THUD_INDEX = 4;
58 static constexpr uint32_t WAVEFORM_SPIN_INDEX = 5;
59 static constexpr uint32_t WAVEFORM_QUICK_RISE_INDEX = 6;
60 static constexpr uint32_t WAVEFORM_SLOW_RISE_INDEX = 7;
61 static constexpr uint32_t WAVEFORM_QUICK_FALL_INDEX = 8;
62 static constexpr uint32_t WAVEFORM_LIGHT_TICK_INDEX = 9;
63 static constexpr uint32_t WAVEFORM_LOW_TICK_INDEX = 10;
64 
65 static constexpr uint32_t WAVEFORM_UNSAVED_TRIGGER_QUEUE_INDEX = 65529;
66 static constexpr uint32_t WAVEFORM_TRIGGER_QUEUE_INDEX = 65534;
67 
68 static constexpr uint32_t VOLTAGE_GLOBAL_SCALE_LEVEL = 5;
69 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
70 
71 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6;  // I2C Transaction + DSP Return-From-Standby
72 static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1;  // ALERT Irq Handling
73 static constexpr uint32_t MAX_TIME_MS = UINT32_MAX;
74 
75 static constexpr float AMP_ATTENUATE_STEP_SIZE = 0.125f;
76 static constexpr float EFFECT_FREQUENCY_KHZ = 48.0f;
77 
78 static constexpr int32_t COMPOSE_DELAY_MAX_MS = 10000;
79 static constexpr int32_t COMPOSE_SIZE_MAX = 127;
80 static constexpr int32_t COMPOSE_PWLE_SIZE_MAX_DEFAULT = 127;
81 
82 
83 // Measured resonant frequency, f0_measured, is represented by Q10.14 fixed
84 // point format on cs40l2x devices. The expression to calculate f0 is:
85 //   f0 = f0_measured / 2^Q14_BIT_SHIFT
86 // See the LRA Calibration Support documentation for more details.
87 static constexpr int32_t Q14_BIT_SHIFT = 14;
88 
89 // Measured Q factor, q_measured, is represented by Q8.16 fixed
90 // point format on cs40l2x devices. The expression to calculate q is:
91 //   q = q_measured / 2^Q16_BIT_SHIFT
92 // See the LRA Calibration Support documentation for more details.
93 static constexpr int32_t Q16_BIT_SHIFT = 16;
94 
95 static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
96 static constexpr float PWLE_LEVEL_MIN = 0.0;
97 static constexpr float PWLE_LEVEL_MAX = 1.0;
98 static constexpr float CS40L2X_PWLE_LEVEL_MAX = 0.999511;
99 static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 0.25;
100 static constexpr float PWLE_FREQUENCY_MIN_HZ = 0.25;
101 static constexpr float PWLE_FREQUENCY_MAX_HZ = 1023.75;
102 static constexpr float PWLE_BW_MAP_SIZE =
103     1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
104 
105 static struct pcm_config haptic_nohost_config = {
106     .channels = 1,
107     .rate = 48000,
108     .period_size = 80,
109     .period_count = 2,
110     .format = PCM_FORMAT_S16_LE,
111 };
112 
amplitudeToScale(float amplitude,float maximum)113 static uint8_t amplitudeToScale(float amplitude, float maximum) {
114     return std::round((-20 * std::log10(amplitude / static_cast<float>(maximum))) /
115                       (AMP_ATTENUATE_STEP_SIZE));
116 }
117 
118 // Discrete points of frequency:max_level pairs as recommended by the document
119 // [R4O6] Max. Allowable Chirp Levels (go/r4o6-max-chirp-levels) around resonant frequency
120 #if defined(LUXSHARE_ICT_081545)
121 static std::map<float, float> discretePwleMaxLevels = {{120.0, 0.4},  {130.0, 0.31}, {140.0, 0.14},
122                                                        {145.0, 0.09}, {150.0, 0.15}, {160.0, 0.35},
123                                                        {170.0, 0.4}};
124 // Discrete points of frequency:max_level pairs as recommended by the document
125 // [P7] Max. Allowable Chirp Levels (go/p7-max-chirp-levels) around resonant frequency
126 #elif defined(LUXSHARE_ICT_LT_XLRA1906D)
127 static std::map<float, float> discretePwleMaxLevels = {{145.0, 0.38}, {150.0, 0.35}, {160.0, 0.35},
128                                                        {170.0, 0.15}, {180.0, 0.35}, {190.0, 0.35},
129                                                        {200.0, 0.38}};
130 #else
131 static std::map<float, float> discretePwleMaxLevels = {};
132 #endif
133 
134 // Initialize all limits to 0.4 according to the document [R4O6] Max. Allowable Chirp Levels
135 // (go/r4o6-max-chirp-levels)
136 #if defined(LUXSHARE_ICT_081545)
137 std::vector<float> pwleMaxLevelLimitMap(PWLE_BW_MAP_SIZE, 0.4);
138 // Initialize all limits to 0.38 according to the document [P7] Max. Allowable Chirp Levels
139 // (go/p7-max-chirp-levels)
140 #elif defined(LUXSHARE_ICT_LT_XLRA1906D)
141 std::vector<float> pwleMaxLevelLimitMap(PWLE_BW_MAP_SIZE, 0.38);
142 #else
143 std::vector<float> pwleMaxLevelLimitMap(PWLE_BW_MAP_SIZE, 1.0);
144 #endif
145 
createPwleMaxLevelLimitMap()146 void Vibrator::createPwleMaxLevelLimitMap() {
147     int32_t capabilities;
148     Vibrator::getCapabilities(&capabilities);
149     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
150         std::map<float, float>::iterator itr0, itr1;
151 
152         if (discretePwleMaxLevels.empty()) {
153             return;
154         }
155         if (discretePwleMaxLevels.size() == 1) {
156             itr0 = discretePwleMaxLevels.begin();
157             float pwleMaxLevelLimitMapIdx =
158                     (itr0->first - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ;
159             pwleMaxLevelLimitMap[pwleMaxLevelLimitMapIdx] = itr0->second;
160             return;
161         }
162 
163         itr0 = discretePwleMaxLevels.begin();
164         itr1 = std::next(itr0, 1);
165 
166         while (itr1 != discretePwleMaxLevels.end()) {
167             float x0 = itr0->first;
168             float y0 = itr0->second;
169             float x1 = itr1->first;
170             float y1 = itr1->second;
171             float pwleMaxLevelLimitMapIdx =
172                     (itr0->first - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ;
173 
174             for (float xp = x0; xp < (x1 + PWLE_FREQUENCY_RESOLUTION_HZ);
175                  xp += PWLE_FREQUENCY_RESOLUTION_HZ) {
176                 float yp = y0 + ((y1 - y0) / (x1 - x0)) * (xp - x0);
177 
178                 pwleMaxLevelLimitMap[pwleMaxLevelLimitMapIdx++] = yp;
179             }
180 
181             itr0++;
182             itr1++;
183         }
184     }
185 }
186 
187 enum class AlwaysOnId : uint32_t {
188     GPIO_RISE,
189     GPIO_FALL,
190 };
191 
Vibrator(std::unique_ptr<HwApi> hwapi,std::unique_ptr<HwCal> hwcal)192 Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal)
193     : mHwApi(std::move(hwapi)), mHwCal(std::move(hwcal)), mAsyncHandle(std::async([] {})) {
194     int32_t longFreqencyShift;
195     uint32_t calVer;
196     uint32_t caldata;
197     uint32_t effectCount;
198 
199     if (!mHwApi->setState(true)) {
200         ALOGE("Failed to set state (%d): %s", errno, strerror(errno));
201     }
202 
203     if (mHwCal->getF0(&caldata)) {
204         mHwApi->setF0(caldata);
205     }
206     if (mHwCal->getRedc(&caldata)) {
207         mHwApi->setRedc(caldata);
208     }
209     if (mHwCal->getQ(&caldata)) {
210         mHwApi->setQ(caldata);
211     }
212 
213     mHwCal->getLongFrequencyShift(&longFreqencyShift);
214     if (longFreqencyShift > 0) {
215         mF0Offset = longFreqencyShift * std::pow(2, 14);
216     } else if (longFreqencyShift < 0) {
217         mF0Offset = std::pow(2, 24) - std::abs(longFreqencyShift) * std::pow(2, 14);
218     } else {
219         mF0Offset = 0;
220     }
221 
222     mHwCal->getVersion(&calVer);
223     if (calVer == 1) {
224         std::array<uint32_t, 6> volLevels;
225         mHwCal->getVolLevels(&volLevels);
226         /*
227          * Given voltage levels for two intensities, assuming a linear function,
228          * solve for 'f(0)' in 'v = f(i) = a + b * i' (i.e 'v0 - (v1 - v0) / ((i1 - i0) / i0)').
229          */
230         mClickEffectVol[0] = std::max(std::lround(volLevels[WAVEFORM_EFFECT_0_20_LEVEL] -
231                                              (volLevels[WAVEFORM_EFFECT_1_00_LEVEL] -
232                                               volLevels[WAVEFORM_EFFECT_0_20_LEVEL]) /
233                                                      4.0f),
234                                  static_cast<long>(WAVEFORM_EFFECT_LEVEL_MINIMUM));
235         mClickEffectVol[1] = volLevels[WAVEFORM_EFFECT_1_00_LEVEL];
236         mTickEffectVol = mClickEffectVol;
237         mLongEffectVol[0] = 0;
238         mLongEffectVol[1] = volLevels[VOLTAGE_GLOBAL_SCALE_LEVEL];
239     } else {
240         mHwCal->getTickVolLevels(&mTickEffectVol);
241         mHwCal->getClickVolLevels(&mClickEffectVol);
242         mHwCal->getLongVolLevels(&mLongEffectVol);
243     }
244 
245     mHwApi->getEffectCount(&effectCount);
246     mEffectDurations.resize(effectCount);
247     for (size_t effectIndex = 0; effectIndex < effectCount; effectIndex++) {
248         mHwApi->setEffectIndex(effectIndex);
249         uint32_t effectDuration;
250         if (mHwApi->getEffectDuration(&effectDuration)) {
251             mEffectDurations[effectIndex] = std::ceil(effectDuration / EFFECT_FREQUENCY_KHZ);
252         }
253     }
254 
255     mHwApi->setClabEnable(true);
256 
257     if (!(getPwleCompositionSizeMax(&compositionSizeMax).isOk())) {
258         ALOGE("Failed to get pwle composition size max, using default size: %d",
259               COMPOSE_PWLE_SIZE_MAX_DEFAULT);
260         compositionSizeMax = COMPOSE_PWLE_SIZE_MAX_DEFAULT;
261     }
262 
263     createPwleMaxLevelLimitMap();
264     mIsUnderExternalControl = false;
265 }
266 
getCapabilities(int32_t * _aidl_return)267 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) {
268     ATRACE_NAME("Vibrator::getCapabilities");
269     int32_t ret = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
270                   IVibrator::CAP_COMPOSE_EFFECTS | IVibrator::CAP_ALWAYS_ON_CONTROL |
271                   IVibrator::CAP_GET_RESONANT_FREQUENCY | IVibrator::CAP_GET_Q_FACTOR;
272     if (mHwApi->hasEffectScale()) {
273         ret |= IVibrator::CAP_AMPLITUDE_CONTROL;
274     }
275     if (mHwApi->hasAspEnable() || hasHapticAlsaDevice()) {
276         ret |= IVibrator::CAP_EXTERNAL_CONTROL;
277     }
278     if (mHwApi->hasPwle()) {
279         ret |= IVibrator::CAP_FREQUENCY_CONTROL | IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
280     }
281     *_aidl_return = ret;
282     return ndk::ScopedAStatus::ok();
283 }
284 
off()285 ndk::ScopedAStatus Vibrator::off() {
286     ATRACE_NAME("Vibrator::off");
287     setGlobalAmplitude(false);
288     mHwApi->setF0Offset(0);
289     if (!mHwApi->setActivate(0)) {
290         ALOGE("Failed to turn vibrator off (%d): %s", errno, strerror(errno));
291         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
292     }
293     return ndk::ScopedAStatus::ok();
294 }
295 
on(int32_t timeoutMs,const std::shared_ptr<IVibratorCallback> & callback)296 ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
297                                 const std::shared_ptr<IVibratorCallback> &callback) {
298     ATRACE_NAME("Vibrator::on");
299     const uint32_t index = timeoutMs < WAVEFORM_LONG_VIBRATION_THRESHOLD_MS
300                                    ? WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX
301                                    : WAVEFORM_LONG_VIBRATION_EFFECT_INDEX;
302     if (MAX_COLD_START_LATENCY_MS <= UINT32_MAX - timeoutMs) {
303         timeoutMs += MAX_COLD_START_LATENCY_MS;
304     }
305     setGlobalAmplitude(true);
306     mHwApi->setF0Offset(mF0Offset);
307     return on(timeoutMs, index, callback);
308 }
309 
perform(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * _aidl_return)310 ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
311                                      const std::shared_ptr<IVibratorCallback> &callback,
312                                      int32_t *_aidl_return) {
313     ATRACE_NAME("Vibrator::perform");
314     return performEffect(effect, strength, callback, _aidl_return);
315 }
316 
getSupportedEffects(std::vector<Effect> * _aidl_return)317 ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect> *_aidl_return) {
318     *_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK,
319                      Effect::DOUBLE_CLICK};
320     return ndk::ScopedAStatus::ok();
321 }
322 
setAmplitude(float amplitude)323 ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
324     ATRACE_NAME("Vibrator::setAmplitude");
325     if (amplitude <= 0.0f || amplitude > 1.0f) {
326         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
327     }
328 
329     if (!isUnderExternalControl()) {
330         return setEffectAmplitude(amplitude, 1.0);
331     } else {
332         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
333     }
334 }
335 
setExternalControl(bool enabled)336 ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
337     ATRACE_NAME("Vibrator::setExternalControl");
338     setGlobalAmplitude(enabled);
339 
340     if (isUnderExternalControl() == enabled) {
341         if (enabled) {
342             ALOGE("Restart the external process.");
343             if (mHasHapticAlsaDevice) {
344                 if (!enableHapticPcmAmp(&mHapticPcm, !enabled, mCard, mDevice)) {
345                     ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"),
346                           mDevice);
347                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
348                 }
349             }
350             if (mHwApi->hasAspEnable()) {
351                 if (!mHwApi->setAspEnable(!enabled)) {
352                     ALOGE("Failed to set external control (%d): %s", errno, strerror(errno));
353                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
354                 }
355             }
356         } else {
357             ALOGE("The external control is already disabled.");
358             return ndk::ScopedAStatus::ok();
359         }
360     }
361     if (mHasHapticAlsaDevice) {
362         if (!enableHapticPcmAmp(&mHapticPcm, enabled, mCard, mDevice)) {
363             ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"), mDevice);
364             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
365         }
366     }
367     if (mHwApi->hasAspEnable()) {
368         if (!mHwApi->setAspEnable(enabled)) {
369             ALOGE("Failed to set external control (%d): %s", errno, strerror(errno));
370             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
371         }
372     }
373 
374     mIsUnderExternalControl = enabled;
375     return ndk::ScopedAStatus::ok();
376 }
377 
getCompositionDelayMax(int32_t * maxDelayMs)378 ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t *maxDelayMs) {
379     ATRACE_NAME("Vibrator::getCompositionDelayMax");
380     *maxDelayMs = COMPOSE_DELAY_MAX_MS;
381     return ndk::ScopedAStatus::ok();
382 }
383 
getCompositionSizeMax(int32_t * maxSize)384 ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t *maxSize) {
385     ATRACE_NAME("Vibrator::getCompositionSizeMax");
386     *maxSize = COMPOSE_SIZE_MAX;
387     return ndk::ScopedAStatus::ok();
388 }
389 
getSupportedPrimitives(std::vector<CompositePrimitive> * supported)390 ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive> *supported) {
391     *supported = {
392             CompositePrimitive::NOOP,       CompositePrimitive::CLICK,
393             CompositePrimitive::THUD,       CompositePrimitive::SPIN,
394             CompositePrimitive::QUICK_RISE, CompositePrimitive::SLOW_RISE,
395             CompositePrimitive::QUICK_FALL, CompositePrimitive::LIGHT_TICK,
396             CompositePrimitive::LOW_TICK,
397     };
398     return ndk::ScopedAStatus::ok();
399 }
400 
getPrimitiveDuration(CompositePrimitive primitive,int32_t * durationMs)401 ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
402                                                   int32_t *durationMs) {
403     ndk::ScopedAStatus status;
404     uint32_t effectIndex;
405 
406     if (primitive != CompositePrimitive::NOOP) {
407         status = getPrimitiveDetails(primitive, &effectIndex);
408         if (!status.isOk()) {
409             return status;
410         }
411 
412         *durationMs = mEffectDurations[effectIndex];
413     } else {
414         *durationMs = 0;
415     }
416 
417     return ndk::ScopedAStatus::ok();
418 }
419 
compose(const std::vector<CompositeEffect> & composite,const std::shared_ptr<IVibratorCallback> & callback)420 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> &composite,
421                                      const std::shared_ptr<IVibratorCallback> &callback) {
422     ATRACE_NAME("Vibrator::compose");
423     std::ostringstream effectBuilder;
424     std::string effectQueue;
425 
426     if (composite.size() > COMPOSE_SIZE_MAX) {
427         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
428     }
429 
430     for (auto &e : composite) {
431         if (e.scale < 0.0f || e.scale > 1.0f) {
432             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
433         }
434 
435         if (e.delayMs) {
436             if (e.delayMs > COMPOSE_DELAY_MAX_MS) {
437                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
438             }
439             effectBuilder << e.delayMs << ",";
440         }
441         if (e.primitive != CompositePrimitive::NOOP) {
442             ndk::ScopedAStatus status;
443             uint32_t effectIndex;
444 
445             status = getPrimitiveDetails(e.primitive, &effectIndex);
446             if (!status.isOk()) {
447                 return status;
448             }
449 
450             effectBuilder << effectIndex << "." << intensityToVolLevel(e.scale, effectIndex) << ",";
451         }
452     }
453 
454     if (effectBuilder.tellp() == 0) {
455         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
456     }
457 
458     effectBuilder << 0;
459 
460     effectQueue = effectBuilder.str();
461 
462     return performEffect(0 /*ignored*/, 0 /*ignored*/, &effectQueue, callback);
463 }
464 
on(uint32_t timeoutMs,uint32_t effectIndex,const std::shared_ptr<IVibratorCallback> & callback)465 ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex,
466                                 const std::shared_ptr<IVibratorCallback> &callback) {
467     if (isUnderExternalControl()) {
468         setExternalControl(false);
469         ALOGE("Device is under external control mode. Force to disable it to prevent chip hang "
470               "problem.");
471     }
472     mHwApi->setActivate(0);
473 
474     mHwApi->setEffectIndex(effectIndex);
475     mHwApi->setDuration(timeoutMs);
476     mHwApi->setActivate(1);
477 
478     mAsyncHandle = std::async(&Vibrator::waitForComplete, this, callback);
479 
480     return ndk::ScopedAStatus::ok();
481 }
482 
setEffectAmplitude(float amplitude,float maximum)483 ndk::ScopedAStatus Vibrator::setEffectAmplitude(float amplitude, float maximum) {
484     int32_t scale = amplitudeToScale(amplitude, maximum);
485 
486     if (!mHwApi->setEffectScale(scale)) {
487         ALOGE("Failed to set effect amplitude (%d): %s", errno, strerror(errno));
488         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
489     }
490 
491     return ndk::ScopedAStatus::ok();
492 }
493 
setGlobalAmplitude(bool set)494 ndk::ScopedAStatus Vibrator::setGlobalAmplitude(bool set) {
495     uint8_t amplitude = set ? mLongEffectVol[1] : VOLTAGE_SCALE_MAX;
496     int32_t scale = amplitudeToScale(amplitude, VOLTAGE_SCALE_MAX);
497 
498     if (!mHwApi->setGlobalScale(scale)) {
499         ALOGE("Failed to set global amplitude (%d): %s", errno, strerror(errno));
500         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
501     }
502 
503     return ndk::ScopedAStatus::ok();
504 }
505 
getSupportedAlwaysOnEffects(std::vector<Effect> * _aidl_return)506 ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect> *_aidl_return) {
507     *_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK};
508     return ndk::ScopedAStatus::ok();
509 }
510 
alwaysOnEnable(int32_t id,Effect effect,EffectStrength strength)511 ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
512     ndk::ScopedAStatus status;
513     uint32_t effectIndex;
514     uint32_t timeMs;
515     uint32_t volLevel;
516     uint32_t scale;
517 
518     status = getSimpleDetails(effect, strength, &effectIndex, &timeMs, &volLevel);
519     if (!status.isOk()) {
520         return status;
521     }
522 
523     scale = amplitudeToScale(volLevel, VOLTAGE_SCALE_MAX);
524 
525     switch (static_cast<AlwaysOnId>(id)) {
526         case AlwaysOnId::GPIO_RISE:
527             mHwApi->setGpioRiseIndex(effectIndex);
528             mHwApi->setGpioRiseScale(scale);
529             return ndk::ScopedAStatus::ok();
530         case AlwaysOnId::GPIO_FALL:
531             mHwApi->setGpioFallIndex(effectIndex);
532             mHwApi->setGpioFallScale(scale);
533             return ndk::ScopedAStatus::ok();
534     }
535 
536     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
537 }
alwaysOnDisable(int32_t id)538 ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t id) {
539     switch (static_cast<AlwaysOnId>(id)) {
540         case AlwaysOnId::GPIO_RISE:
541             mHwApi->setGpioRiseIndex(0);
542             return ndk::ScopedAStatus::ok();
543         case AlwaysOnId::GPIO_FALL:
544             mHwApi->setGpioFallIndex(0);
545             return ndk::ScopedAStatus::ok();
546     }
547 
548     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
549 }
550 
getResonantFrequency(float * resonantFreqHz)551 ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
552     uint32_t caldata;
553     if (!mHwCal->getF0(&caldata)) {
554         ALOGE("Failed to get resonant frequency (%d): %s", errno, strerror(errno));
555         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
556     }
557     *resonantFreqHz = static_cast<float>(caldata) / (1 << Q14_BIT_SHIFT);
558 
559     return ndk::ScopedAStatus::ok();
560 }
561 
getQFactor(float * qFactor)562 ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
563     uint32_t caldata;
564     if (!mHwCal->getQ(&caldata)) {
565         ALOGE("Failed to get q factor (%d): %s", errno, strerror(errno));
566         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
567     }
568     *qFactor = static_cast<float>(caldata) / (1 << Q16_BIT_SHIFT);
569 
570     return ndk::ScopedAStatus::ok();
571 }
572 
getFrequencyResolution(float * freqResolutionHz)573 ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
574     int32_t capabilities;
575     Vibrator::getCapabilities(&capabilities);
576     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
577         *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
578         return ndk::ScopedAStatus::ok();
579     } else {
580         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
581     }
582 }
583 
getFrequencyMinimum(float * freqMinimumHz)584 ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
585     int32_t capabilities;
586     Vibrator::getCapabilities(&capabilities);
587     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
588         *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
589         return ndk::ScopedAStatus::ok();
590     } else {
591         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
592     }
593 }
594 
getBandwidthAmplitudeMap(std::vector<float> * _aidl_return)595 ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
596     // TODO(b/170919640): complete implementation
597     int32_t capabilities;
598     Vibrator::getCapabilities(&capabilities);
599     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
600         std::vector<float> bandwidthAmplitudeMap(PWLE_BW_MAP_SIZE, 1.0);
601         *_aidl_return = bandwidthAmplitudeMap;
602         return ndk::ScopedAStatus::ok();
603     } else {
604         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
605     }
606 }
607 
getPwlePrimitiveDurationMax(int32_t * durationMs)608 ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
609     int32_t capabilities;
610     Vibrator::getCapabilities(&capabilities);
611     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
612         *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
613         return ndk::ScopedAStatus::ok();
614     } else {
615         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
616     }
617 }
618 
getPwleCompositionSizeMax(int32_t * maxSize)619 ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
620     int32_t capabilities;
621     Vibrator::getCapabilities(&capabilities);
622     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
623         uint32_t segments;
624         if (!mHwApi->getAvailablePwleSegments(&segments)) {
625             ALOGE("Failed to get availablePwleSegments (%d): %s", errno, strerror(errno));
626             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
627         }
628         *maxSize = segments;
629         return ndk::ScopedAStatus::ok();
630     } else {
631         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
632     }
633 }
634 
getSupportedBraking(std::vector<Braking> * supported)635 ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
636     int32_t capabilities;
637     Vibrator::getCapabilities(&capabilities);
638     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
639         *supported = {
640             Braking::NONE,
641             Braking::CLAB,
642         };
643         return ndk::ScopedAStatus::ok();
644     } else {
645         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
646     }
647 }
648 
setPwle(const std::string & pwleQueue)649 ndk::ScopedAStatus Vibrator::setPwle(const std::string &pwleQueue) {
650     if (!mHwApi->setPwle(pwleQueue)) {
651         ALOGE("Failed to write \"%s\" to pwle (%d): %s", pwleQueue.c_str(), errno, strerror(errno));
652         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
653     }
654 
655     return ndk::ScopedAStatus::ok();
656 }
657 
resetPreviousEndAmplitudeEndFrequency(float & prevEndAmplitude,float & prevEndFrequency)658 static void resetPreviousEndAmplitudeEndFrequency(float &prevEndAmplitude,
659                                                   float &prevEndFrequency) {
660     const float reset = -1.0;
661     prevEndAmplitude = reset;
662     prevEndFrequency = reset;
663 }
664 
incrementIndex(int & index)665 static void incrementIndex(int &index) {
666     index += 1;
667 }
668 
constructActiveDefaults(std::ostringstream & pwleBuilder,const int & segmentIdx)669 static void constructActiveDefaults(std::ostringstream &pwleBuilder, const int &segmentIdx) {
670     pwleBuilder << ",C" << segmentIdx << ":1";
671     pwleBuilder << ",B" << segmentIdx << ":0";
672     pwleBuilder << ",AR" << segmentIdx << ":0";
673     pwleBuilder << ",V" << segmentIdx << ":0";
674 }
675 
constructActiveSegment(std::ostringstream & pwleBuilder,const int & segmentIdx,int duration,float amplitude,float frequency)676 static void constructActiveSegment(std::ostringstream &pwleBuilder, const int &segmentIdx,
677                                    int duration, float amplitude, float frequency) {
678     pwleBuilder << ",T" << segmentIdx << ":" << duration;
679     pwleBuilder << ",L" << segmentIdx << ":" << amplitude;
680     pwleBuilder << ",F" << segmentIdx << ":" << frequency;
681     constructActiveDefaults(pwleBuilder, segmentIdx);
682 }
683 
constructBrakingSegment(std::ostringstream & pwleBuilder,const int & segmentIdx,int duration,Braking brakingType)684 static void constructBrakingSegment(std::ostringstream &pwleBuilder, const int &segmentIdx,
685                                     int duration, Braking brakingType) {
686     pwleBuilder << ",T" << segmentIdx << ":" << duration;
687     pwleBuilder << ",L" << segmentIdx << ":" << 0;
688     pwleBuilder << ",F" << segmentIdx << ":" << PWLE_FREQUENCY_MIN_HZ;
689     pwleBuilder << ",C" << segmentIdx << ":0";
690     pwleBuilder << ",B" << segmentIdx << ":"
691                 << static_cast<std::underlying_type<Braking>::type>(brakingType);
692     pwleBuilder << ",AR" << segmentIdx << ":0";
693     pwleBuilder << ",V" << segmentIdx << ":0";
694 }
695 
composePwle(const std::vector<PrimitivePwle> & composite,const std::shared_ptr<IVibratorCallback> & callback)696 ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
697                                          const std::shared_ptr<IVibratorCallback> &callback) {
698     ATRACE_NAME("Vibrator::composePwle");
699     std::ostringstream pwleBuilder;
700     std::string pwleQueue;
701 
702     if (composite.size() <= 0 || composite.size() > compositionSizeMax) {
703         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
704     }
705 
706     float prevEndAmplitude;
707     float prevEndFrequency;
708     resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
709 
710     int segmentIdx = 0;
711     uint32_t totalDuration = 0;
712 
713     pwleBuilder << "S:0,WF:4,RP:0,WT:0";
714 
715     for (auto &e : composite) {
716         switch (e.getTag()) {
717             case PrimitivePwle::active: {
718                 auto active = e.get<PrimitivePwle::active>();
719                 if (active.duration < 0 ||
720                     active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
721                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
722                 }
723                 if (active.startAmplitude < PWLE_LEVEL_MIN ||
724                     active.startAmplitude > PWLE_LEVEL_MAX ||
725                     active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
726                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
727                 }
728                 if (active.startAmplitude > CS40L2X_PWLE_LEVEL_MAX) {
729                     active.startAmplitude = CS40L2X_PWLE_LEVEL_MAX;
730                 }
731                 if (active.endAmplitude > CS40L2X_PWLE_LEVEL_MAX) {
732                     active.endAmplitude = CS40L2X_PWLE_LEVEL_MAX;
733                 }
734 
735                 if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
736                     active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
737                     active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
738                     active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
739                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
740                 }
741 
742                 // clip to the hard limit on input level from pwleMaxLevelLimitMap
743                 float maxLevelLimit =
744                     pwleMaxLevelLimitMap[active.startFrequency / PWLE_FREQUENCY_RESOLUTION_HZ - 1];
745                 if (active.startAmplitude > maxLevelLimit) {
746                     active.startAmplitude = maxLevelLimit;
747                 }
748                 maxLevelLimit =
749                     pwleMaxLevelLimitMap[active.endFrequency / PWLE_FREQUENCY_RESOLUTION_HZ - 1];
750                 if (active.endAmplitude > maxLevelLimit) {
751                     active.endAmplitude = maxLevelLimit;
752                 }
753 
754                 if (!((active.startAmplitude == prevEndAmplitude) &&
755                       (active.startFrequency == prevEndFrequency))) {
756                     constructActiveSegment(pwleBuilder, segmentIdx, 0, active.startAmplitude,
757                                            active.startFrequency);
758                     incrementIndex(segmentIdx);
759                 }
760 
761                 constructActiveSegment(pwleBuilder, segmentIdx, active.duration,
762                                        active.endAmplitude, active.endFrequency);
763                 incrementIndex(segmentIdx);
764 
765                 prevEndAmplitude = active.endAmplitude;
766                 prevEndFrequency = active.endFrequency;
767                 totalDuration += active.duration;
768                 break;
769             }
770             case PrimitivePwle::braking: {
771                 auto braking = e.get<PrimitivePwle::braking>();
772                 if (braking.braking > Braking::CLAB) {
773                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
774                 }
775                 if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
776                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
777                 }
778 
779                 constructBrakingSegment(pwleBuilder, segmentIdx, 0, braking.braking);
780                 incrementIndex(segmentIdx);
781 
782                 constructBrakingSegment(pwleBuilder, segmentIdx, braking.duration, braking.braking);
783                 incrementIndex(segmentIdx);
784 
785                 resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
786                 totalDuration += braking.duration;
787                 break;
788             }
789         }
790     }
791 
792     pwleQueue = pwleBuilder.str();
793     ALOGD("composePwle queue: (%s)", pwleQueue.c_str());
794 
795     ndk::ScopedAStatus status = setPwle(pwleQueue);
796     if (!status.isOk()) {
797         ALOGE("Failed to write pwle queue");
798         return status;
799     }
800 
801     setEffectAmplitude(VOLTAGE_SCALE_MAX, VOLTAGE_SCALE_MAX);
802     mHwApi->setEffectIndex(WAVEFORM_UNSAVED_TRIGGER_QUEUE_INDEX);
803 
804     totalDuration += MAX_COLD_START_LATENCY_MS;
805     mHwApi->setDuration(MAX_TIME_MS);
806 
807     mHwApi->setActivate(1);
808 
809     mAsyncHandle = std::async(&Vibrator::waitForComplete, this, callback);
810 
811     return ndk::ScopedAStatus::ok();
812 }
813 
isUnderExternalControl()814 bool Vibrator::isUnderExternalControl() {
815     return mIsUnderExternalControl;
816 }
817 
dump(int fd,const char ** args,uint32_t numArgs)818 binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
819     if (fd < 0) {
820         ALOGE("Called debug() with invalid fd.");
821         return STATUS_OK;
822     }
823 
824     (void)args;
825     (void)numArgs;
826 
827     dprintf(fd, "AIDL:\n");
828 
829     dprintf(fd, "  F0 Offset: %" PRIu32 "\n", mF0Offset);
830 
831     dprintf(fd, "  Voltage Levels:\n");
832     dprintf(fd, "    Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n",
833             mTickEffectVol[0], mTickEffectVol[1]);
834     dprintf(fd, "    Click Effect Min: %" PRIu32 " Max: %" PRIu32 "\n",
835             mClickEffectVol[0], mClickEffectVol[1]);
836     dprintf(fd, "    Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n",
837             mLongEffectVol[0], mLongEffectVol[1]);
838 
839     dprintf(fd, "  Effect Durations:");
840     for (auto d : mEffectDurations) {
841         dprintf(fd, " %" PRIu32, d);
842     }
843     dprintf(fd, "\n");
844 
845     dprintf(fd, "\n");
846 
847     mHwApi->debug(fd);
848 
849     dprintf(fd, "\n");
850 
851     mHwCal->debug(fd);
852 
853     fsync(fd);
854     return STATUS_OK;
855 }
856 
getSimpleDetails(Effect effect,EffectStrength strength,uint32_t * outEffectIndex,uint32_t * outTimeMs,uint32_t * outVolLevel)857 ndk::ScopedAStatus Vibrator::getSimpleDetails(Effect effect, EffectStrength strength,
858                                               uint32_t *outEffectIndex, uint32_t *outTimeMs,
859                                               uint32_t *outVolLevel) {
860     uint32_t effectIndex;
861     uint32_t timeMs;
862     float intensity;
863     uint32_t volLevel;
864 
865     switch (strength) {
866         case EffectStrength::LIGHT:
867             intensity = 0.5f;
868             break;
869         case EffectStrength::MEDIUM:
870             intensity = 0.7f;
871             break;
872         case EffectStrength::STRONG:
873             intensity = 1.0f;
874             break;
875         default:
876             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
877     }
878 
879     switch (effect) {
880         case Effect::TEXTURE_TICK:
881             effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
882             intensity *= 0.5f;
883             break;
884         case Effect::TICK:
885             effectIndex = WAVEFORM_CLICK_INDEX;
886             intensity *= 0.5f;
887             break;
888         case Effect::CLICK:
889             effectIndex = WAVEFORM_CLICK_INDEX;
890             intensity *= 0.7f;
891             break;
892         case Effect::HEAVY_CLICK:
893             effectIndex = WAVEFORM_CLICK_INDEX;
894             intensity *= 1.0f;
895             break;
896         default:
897             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
898     }
899 
900     volLevel = intensityToVolLevel(intensity, effectIndex);
901     timeMs = mEffectDurations[effectIndex] + MAX_COLD_START_LATENCY_MS;
902 
903     *outEffectIndex = effectIndex;
904     *outTimeMs = timeMs;
905     *outVolLevel = volLevel;
906 
907     return ndk::ScopedAStatus::ok();
908 }
909 
getCompoundDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,uint32_t *,std::string * outEffectQueue)910 ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength strength,
911                                                 uint32_t *outTimeMs, uint32_t * /*outVolLevel*/,
912                                                 std::string *outEffectQueue) {
913     ndk::ScopedAStatus status;
914     uint32_t timeMs;
915     std::ostringstream effectBuilder;
916     uint32_t thisEffectIndex;
917     uint32_t thisTimeMs;
918     uint32_t thisVolLevel;
919 
920     switch (effect) {
921         case Effect::DOUBLE_CLICK:
922             timeMs = 0;
923 
924             status = getSimpleDetails(Effect::CLICK, strength, &thisEffectIndex, &thisTimeMs,
925                                       &thisVolLevel);
926             if (!status.isOk()) {
927                 return status;
928             }
929             effectBuilder << thisEffectIndex << "." << thisVolLevel;
930             timeMs += thisTimeMs;
931 
932             effectBuilder << ",";
933 
934             effectBuilder << WAVEFORM_DOUBLE_CLICK_SILENCE_MS;
935             timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS;
936 
937             effectBuilder << ",";
938 
939             status = getSimpleDetails(Effect::HEAVY_CLICK, strength, &thisEffectIndex, &thisTimeMs,
940                                       &thisVolLevel);
941             if (!status.isOk()) {
942                 return status;
943             }
944             effectBuilder << thisEffectIndex << "." << thisVolLevel;
945             timeMs += thisTimeMs;
946 
947             break;
948         default:
949             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
950     }
951 
952     *outTimeMs = timeMs;
953     *outEffectQueue = effectBuilder.str();
954 
955     return ndk::ScopedAStatus::ok();
956 }
957 
getPrimitiveDetails(CompositePrimitive primitive,uint32_t * outEffectIndex)958 ndk::ScopedAStatus Vibrator::getPrimitiveDetails(CompositePrimitive primitive,
959                                                  uint32_t *outEffectIndex) {
960     uint32_t effectIndex;
961 
962     switch (primitive) {
963         case CompositePrimitive::NOOP:
964             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
965         case CompositePrimitive::CLICK:
966             effectIndex = WAVEFORM_CLICK_INDEX;
967             break;
968         case CompositePrimitive::THUD:
969             effectIndex = WAVEFORM_THUD_INDEX;
970             break;
971         case CompositePrimitive::SPIN:
972             effectIndex = WAVEFORM_SPIN_INDEX;
973             break;
974         case CompositePrimitive::QUICK_RISE:
975             effectIndex = WAVEFORM_QUICK_RISE_INDEX;
976             break;
977         case CompositePrimitive::SLOW_RISE:
978             effectIndex = WAVEFORM_SLOW_RISE_INDEX;
979             break;
980         case CompositePrimitive::QUICK_FALL:
981             effectIndex = WAVEFORM_QUICK_FALL_INDEX;
982             break;
983         case CompositePrimitive::LIGHT_TICK:
984             effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
985             break;
986         case CompositePrimitive::LOW_TICK:
987             effectIndex = WAVEFORM_LOW_TICK_INDEX;
988             break;
989         default:
990             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
991     }
992 
993     *outEffectIndex = effectIndex;
994 
995     return ndk::ScopedAStatus::ok();
996 }
997 
setEffectQueue(const std::string & effectQueue)998 ndk::ScopedAStatus Vibrator::setEffectQueue(const std::string &effectQueue) {
999     if (!mHwApi->setEffectQueue(effectQueue)) {
1000         ALOGE("Failed to write \"%s\" to effect queue (%d): %s", effectQueue.c_str(), errno,
1001               strerror(errno));
1002         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1003     }
1004 
1005     return ndk::ScopedAStatus::ok();
1006 }
1007 
performEffect(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * outTimeMs)1008 ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strength,
1009                                            const std::shared_ptr<IVibratorCallback> &callback,
1010                                            int32_t *outTimeMs) {
1011     ndk::ScopedAStatus status;
1012     uint32_t effectIndex;
1013     uint32_t timeMs = 0;
1014     uint32_t volLevel;
1015     std::string effectQueue;
1016 
1017     switch (effect) {
1018         case Effect::TEXTURE_TICK:
1019             // fall-through
1020         case Effect::TICK:
1021             // fall-through
1022         case Effect::CLICK:
1023             // fall-through
1024         case Effect::HEAVY_CLICK:
1025             status = getSimpleDetails(effect, strength, &effectIndex, &timeMs, &volLevel);
1026             break;
1027         case Effect::DOUBLE_CLICK:
1028             status = getCompoundDetails(effect, strength, &timeMs, &volLevel, &effectQueue);
1029             break;
1030         default:
1031             status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1032             break;
1033     }
1034     if (!status.isOk()) {
1035         goto exit;
1036     }
1037 
1038     status = performEffect(effectIndex, volLevel, &effectQueue, callback);
1039 
1040 exit:
1041 
1042     *outTimeMs = timeMs;
1043     return status;
1044 }
1045 
performEffect(uint32_t effectIndex,uint32_t volLevel,const std::string * effectQueue,const std::shared_ptr<IVibratorCallback> & callback)1046 ndk::ScopedAStatus Vibrator::performEffect(uint32_t effectIndex, uint32_t volLevel,
1047                                            const std::string *effectQueue,
1048                                            const std::shared_ptr<IVibratorCallback> &callback) {
1049     if (effectQueue && !effectQueue->empty()) {
1050         ndk::ScopedAStatus status = setEffectQueue(*effectQueue);
1051         if (!status.isOk()) {
1052             return status;
1053         }
1054         setEffectAmplitude(VOLTAGE_SCALE_MAX, VOLTAGE_SCALE_MAX);
1055         effectIndex = WAVEFORM_TRIGGER_QUEUE_INDEX;
1056     } else {
1057         setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX);
1058     }
1059 
1060     return on(MAX_TIME_MS, effectIndex, callback);
1061 }
1062 
waitForComplete(std::shared_ptr<IVibratorCallback> && callback)1063 void Vibrator::waitForComplete(std::shared_ptr<IVibratorCallback> &&callback) {
1064     mHwApi->pollVibeState(false);
1065     mHwApi->setActivate(false);
1066 
1067     if (callback) {
1068         auto ret = callback->onComplete();
1069         if (!ret.isOk()) {
1070             ALOGE("Failed completion callback: %d", ret.getExceptionCode());
1071         }
1072     }
1073 }
1074 
intensityToVolLevel(float intensity,uint32_t effectIndex)1075 uint32_t Vibrator::intensityToVolLevel(float intensity, uint32_t effectIndex) {
1076 
1077     uint32_t volLevel;
1078     auto calc = [](float intst, std::array<uint32_t, 2> v) -> uint32_t {
1079                 return std::lround(intst * (v[1] - v[0])) + v[0]; };
1080 
1081     switch (effectIndex) {
1082         case WAVEFORM_LIGHT_TICK_INDEX:
1083             volLevel = calc(intensity, mTickEffectVol);
1084             break;
1085         case WAVEFORM_QUICK_RISE_INDEX:
1086             // fall-through
1087         case WAVEFORM_QUICK_FALL_INDEX:
1088             volLevel = calc(intensity, mLongEffectVol);
1089             break;
1090         case WAVEFORM_CLICK_INDEX:
1091             // fall-through
1092         case WAVEFORM_THUD_INDEX:
1093             // fall-through
1094         case WAVEFORM_SPIN_INDEX:
1095             // fall-through
1096         case WAVEFORM_SLOW_RISE_INDEX:
1097             // fall-through
1098         default:
1099             volLevel = calc(intensity, mClickEffectVol);
1100             break;
1101     }
1102 
1103     return volLevel;
1104 }
1105 
findHapticAlsaDevice(int * card,int * device)1106 bool Vibrator::findHapticAlsaDevice(int *card, int *device) {
1107     std::string line;
1108     std::ifstream myfile(PROC_SND_PCM);
1109     if (myfile.is_open()) {
1110         while (getline(myfile, line)) {
1111             if (line.find(HAPTIC_PCM_DEVICE_SYMBOL) != std::string::npos) {
1112                 std::stringstream ss(line);
1113                 std::string currentToken;
1114                 std::getline(ss, currentToken, ':');
1115                 sscanf(currentToken.c_str(), "%d-%d", card, device);
1116                 return true;
1117             }
1118         }
1119         myfile.close();
1120     } else {
1121         ALOGE("Failed to read file: %s", PROC_SND_PCM);
1122     }
1123     return false;
1124 }
1125 
hasHapticAlsaDevice()1126 bool Vibrator::hasHapticAlsaDevice() {
1127     // We need to call findHapticAlsaDevice once only. Calling in the
1128     // constructor is too early in the boot process and the pcm file contents
1129     // are empty. Hence we make the call here once only right before we need to.
1130     static bool configHapticAlsaDeviceDone = false;
1131     if (!configHapticAlsaDeviceDone) {
1132         if (findHapticAlsaDevice(&mCard, &mDevice)) {
1133             mHasHapticAlsaDevice = true;
1134             configHapticAlsaDeviceDone = true;
1135         } else {
1136             ALOGE("Haptic ALSA device not supported");
1137         }
1138     }
1139     return mHasHapticAlsaDevice;
1140 }
1141 
enableHapticPcmAmp(struct pcm ** haptic_pcm,bool enable,int card,int device)1142 bool Vibrator::enableHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device) {
1143     int ret = 0;
1144 
1145     if (enable) {
1146         *haptic_pcm = pcm_open(card, device, PCM_OUT, &haptic_nohost_config);
1147         if (!pcm_is_ready(*haptic_pcm)) {
1148             ALOGE("cannot open pcm_out driver: %s", pcm_get_error(*haptic_pcm));
1149             goto fail;
1150         }
1151 
1152         ret = pcm_prepare(*haptic_pcm);
1153         if (ret < 0) {
1154             ALOGE("cannot prepare haptic_pcm: %s", pcm_get_error(*haptic_pcm));
1155             goto fail;
1156         }
1157 
1158         ret = pcm_start(*haptic_pcm);
1159         if (ret < 0) {
1160             ALOGE("cannot start haptic_pcm: %s", pcm_get_error(*haptic_pcm));
1161             goto fail;
1162         }
1163 
1164         return true;
1165     } else {
1166         if (*haptic_pcm) {
1167             pcm_close(*haptic_pcm);
1168             *haptic_pcm = NULL;
1169         }
1170         return true;
1171     }
1172 
1173 fail:
1174     pcm_close(*haptic_pcm);
1175     *haptic_pcm = NULL;
1176     return false;
1177 }
1178 
1179 }  // namespace vibrator
1180 }  // namespace hardware
1181 }  // namespace android
1182 }  // namespace aidl
1183