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