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