1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "Vibrator.h"
18
19 #include <android-base/properties.h>
20 #include <hardware/hardware.h>
21 #include <hardware/vibrator.h>
22 #include <log/log.h>
23 #include <utils/Trace.h>
24
25 #include <chrono>
26 #include <cinttypes>
27 #include <cmath>
28 #include <fstream>
29 #include <iostream>
30 #include <map>
31 #include <memory>
32 #include <optional>
33 #include <sstream>
34
35 #include "Stats.h"
36
37 #ifndef ARRAY_SIZE
38 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
39 #endif
40
41 namespace aidl {
42 namespace android {
43 namespace hardware {
44 namespace vibrator {
45
46 #ifdef HAPTIC_TRACE
47 #define HAPTICS_TRACE(...) ALOGD(__VA_ARGS__)
48 #else
49 #define HAPTICS_TRACE(...)
50 #endif
51
52 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_COMP = 2044; // (COMPOSE_SIZE_MAX + 1) * 8 + 4
53 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_PWLE = 2302;
54
55 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_SILENCE_MS = 100;
56
57 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_THRESHOLD_MS = 50;
58
59 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
60
61 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby
62 static constexpr uint32_t MIN_ON_OFF_INTERVAL_US = 8500; // SVC initialization time
63 static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1; // ALERT Irq Handling
64 static constexpr uint32_t MAX_TIME_MS = UINT16_MAX;
65
66 static constexpr auto ASYNC_COMPLETION_TIMEOUT = std::chrono::milliseconds(100);
67 static constexpr auto POLLING_TIMEOUT = 50; // POLLING_TIMEOUT < ASYNC_COMPLETION_TIMEOUT
68 static constexpr int32_t COMPOSE_DELAY_MAX_MS = 10000;
69
70 /* nsections is 8 bits. Need to preserve 1 section for the first delay before the first effect. */
71 static constexpr int32_t COMPOSE_SIZE_MAX = 254;
72 static constexpr int32_t COMPOSE_PWLE_SIZE_MAX_DEFAULT = 127;
73
74 // Measured resonant frequency, f0_measured, is represented by Q10.14 fixed
75 // point format on cs40l26 devices. The expression to calculate f0 is:
76 // f0 = f0_measured / 2^Q14_BIT_SHIFT
77 // See the LRA Calibration Support documentation for more details.
78 static constexpr int32_t Q14_BIT_SHIFT = 14;
79
80 // Measured ReDC. The LRA series resistance (ReDC), expressed as follows
81 // redc(ohms) = redc_measured / 2^Q15_BIT_SHIFT.
82 // This value represents the unit-specific ReDC input to the click compensation
83 // algorithm. It can be overwritten at a later time by writing to the redc_stored
84 // sysfs control.
85 // See the LRA Calibration Support documentation for more details.
86 static constexpr int32_t Q15_BIT_SHIFT = 15;
87
88 // Measured Q factor, q_measured, is represented by Q8.16 fixed
89 // point format on cs40l26 devices. The expression to calculate q is:
90 // q = q_measured / 2^Q16_BIT_SHIFT
91 // See the LRA Calibration Support documentation for more details.
92 static constexpr int32_t Q16_BIT_SHIFT = 16;
93
94 static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
95
96 static constexpr uint32_t WT_LEN_CALCD = 0x00800000;
97 static constexpr uint8_t PWLE_CHIRP_BIT = 0x8; // Dynamic/static frequency and voltage
98 static constexpr uint8_t PWLE_BRAKE_BIT = 0x4;
99 static constexpr uint8_t PWLE_AMP_REG_BIT = 0x2;
100
101 static constexpr float PWLE_LEVEL_MIN = 0.0;
102 static constexpr float PWLE_LEVEL_MAX = 1.0;
103 static constexpr float CS40L26_PWLE_LEVEL_MIN = -1.0;
104 static constexpr float CS40L26_PWLE_LEVEL_MAX = 0.9995118;
105 static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.00;
106 static constexpr float PWLE_FREQUENCY_MIN_HZ = 30.0f;
107 static constexpr float RESONANT_FREQUENCY_DEFAULT = 145.0f;
108 static constexpr float PWLE_FREQUENCY_MAX_HZ = 300.0f;
109 static constexpr float PWLE_BW_MAP_SIZE =
110 1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
111
112 enum WaveformBankID : uint8_t {
113 RAM_WVFRM_BANK,
114 ROM_WVFRM_BANK,
115 OWT_WVFRM_BANK,
116 };
117
118 enum WaveformIndex : uint16_t {
119 /* Physical waveform */
120 WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
121 WAVEFORM_RESERVED_INDEX_1 = 1,
122 WAVEFORM_CLICK_INDEX = 2,
123 WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
124 WAVEFORM_THUD_INDEX = 4,
125 WAVEFORM_SPIN_INDEX = 5,
126 WAVEFORM_QUICK_RISE_INDEX = 6,
127 WAVEFORM_SLOW_RISE_INDEX = 7,
128 WAVEFORM_QUICK_FALL_INDEX = 8,
129 WAVEFORM_LIGHT_TICK_INDEX = 9,
130 WAVEFORM_LOW_TICK_INDEX = 10,
131 WAVEFORM_RESERVED_MFG_1,
132 WAVEFORM_RESERVED_MFG_2,
133 WAVEFORM_RESERVED_MFG_3,
134 WAVEFORM_MAX_PHYSICAL_INDEX,
135 /* OWT waveform */
136 WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
137 WAVEFORM_PWLE,
138 /*
139 * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
140 * #define FF_GAIN 0x60 // 96 in decimal
141 * #define FF_MAX_EFFECTS FF_GAIN
142 */
143 WAVEFORM_MAX_INDEX,
144 };
145
146 std::vector<CompositePrimitive> defaultSupportedPrimitives = {
147 ndk::enum_range<CompositePrimitive>().begin(), ndk::enum_range<CompositePrimitive>().end()};
148
149 enum vibe_state {
150 VIBE_STATE_STOPPED = 0,
151 VIBE_STATE_HAPTIC,
152 VIBE_STATE_ASP,
153 };
154
155 std::mutex mActiveId_mutex; // protects mActiveId
156
157 class DspMemChunk {
158 private:
159 std::unique_ptr<uint8_t[]> head;
160 size_t bytes = 0;
161 uint8_t waveformType;
162 uint8_t *_current;
163 const uint8_t *_max;
164 uint32_t _cache = 0;
165 int _cachebits = 0;
166
isEnd() const167 bool isEnd() const { return _current == _max; }
min(int x,int y)168 int min(int x, int y) { return x < y ? x : y; }
169
write(int nbits,uint32_t val)170 int write(int nbits, uint32_t val) {
171 HAPTICS_TRACE(" DspMemChunk::write(nbits:%d, val:%u)", nbits, val);
172 int nwrite, i;
173
174 nwrite = min(24 - _cachebits, nbits);
175 _cache <<= nwrite;
176 _cache |= val >> (nbits - nwrite);
177 _cachebits += nwrite;
178 nbits -= nwrite;
179
180 if (_cachebits == 24) {
181 if (isEnd())
182 return -ENOSPC;
183
184 _cache &= 0xFFFFFF;
185 for (i = 0; i < sizeof(_cache); i++, _cache <<= 8)
186 *_current++ = (_cache & 0xFF000000) >> 24;
187
188 bytes += sizeof(_cache);
189 _cachebits = 0;
190 }
191
192 if (nbits)
193 return write(nbits, val);
194
195 return 0;
196 }
197
fToU16(float input,uint16_t * output,float scale,float min,float max)198 int fToU16(float input, uint16_t *output, float scale, float min, float max) {
199 HAPTICS_TRACE(" DspMemChunk::fToU16(input:%f, output, scale:%f, min:%f, max:%f", input,
200 scale, min, max);
201 if (input < min || input > max)
202 return -ERANGE;
203
204 *output = roundf(input * scale);
205 return 0;
206 }
207
constructPwleSegment(uint16_t delay,uint16_t amplitude,uint16_t frequency,uint8_t flags,uint32_t vbemfTarget=0)208 void constructPwleSegment(uint16_t delay, uint16_t amplitude, uint16_t frequency, uint8_t flags,
209 uint32_t vbemfTarget = 0) {
210 HAPTICS_TRACE(
211 " constructPwleSegment(ch, delay:%u, amplitude:%u, frequency:%u, flags:%u"
212 ", vbemfTarget:%u)",
213 delay, amplitude, frequency, flags, vbemfTarget);
214 write(16, delay);
215 write(12, amplitude);
216 write(12, frequency);
217 /* feature flags to control the chirp, CLAB braking, back EMF amplitude regulation */
218 write(8, (flags | 1) << 4);
219 if (flags & PWLE_AMP_REG_BIT) {
220 write(24, vbemfTarget); /* target back EMF voltage */
221 }
222 }
223
224 public:
front() const225 uint8_t *front() const { return head.get(); }
type() const226 uint8_t type() const { return waveformType; }
size() const227 size_t size() const { return bytes; }
228
DspMemChunk(uint8_t type,size_t size)229 DspMemChunk(uint8_t type, size_t size) : head(new uint8_t[size]{0x00}) {
230 HAPTICS_TRACE(" DspMemChunk(size:%zu)", size);
231 waveformType = type;
232 _current = head.get();
233 _max = _current + size;
234
235 if (waveformType == WAVEFORM_COMPOSE) {
236 write(8, 0); /* Padding */
237 write(8, 0); /* nsections placeholder */
238 write(8, 0); /* repeat */
239 } else if (waveformType == WAVEFORM_PWLE) {
240 write(24, 0); /* Waveform length placeholder */
241 write(8, 0); /* Repeat */
242 write(12, 0); /* Wait time between repeats */
243 write(8, 0); /* nsections placeholder */
244 } else {
245 ALOGE("%s: Invalid type: %u", __func__, waveformType);
246 }
247 }
248
flush()249 int flush() {
250 HAPTICS_TRACE(" DspMemChunk::flush()");
251 if (!_cachebits)
252 return 0;
253
254 return write(24 - _cachebits, 0);
255 }
256
constructComposeSegment(uint32_t effectVolLevel,uint32_t effectIndex,uint8_t repeat,uint8_t flags,uint16_t nextEffectDelay)257 int constructComposeSegment(uint32_t effectVolLevel, uint32_t effectIndex, uint8_t repeat,
258 uint8_t flags, uint16_t nextEffectDelay) {
259 HAPTICS_TRACE(
260 " constructComposeSegment(effectVolLevel:%u, effectIndex:%u, repeat:%d, "
261 "flags:%d, nextEffectDelay:%u",
262 effectVolLevel, effectIndex, repeat, flags, nextEffectDelay);
263 if (waveformType != WAVEFORM_COMPOSE) {
264 ALOGE("%s: Invalid type: %d", __func__, waveformType);
265 return -EDOM;
266 }
267 if (effectVolLevel > 100 || effectIndex > WAVEFORM_MAX_PHYSICAL_INDEX) {
268 ALOGE("%s: Invalid argument: %u, %u", __func__, effectVolLevel, effectIndex);
269 return -EINVAL;
270 }
271 write(8, effectVolLevel); /* amplitude */
272 write(8, effectIndex); /* index */
273 write(8, repeat); /* repeat */
274 write(8, flags); /* flags */
275 write(16, nextEffectDelay); /* delay */
276 return 0;
277 }
278
constructActiveSegment(int duration,float amplitude,float frequency,bool chirp)279 int constructActiveSegment(int duration, float amplitude, float frequency, bool chirp) {
280 HAPTICS_TRACE(" constructActiveSegment(duration:%d, amplitude:%f, frequency:%f)",
281 duration, amplitude, frequency);
282 uint16_t delay = 0;
283 uint16_t amp = 0;
284 uint16_t freq = 0;
285 uint8_t flags = 0x0;
286 if (waveformType != WAVEFORM_PWLE) {
287 ALOGE("%s: Invalid type: %d", __func__, waveformType);
288 return -EDOM;
289 }
290 if ((fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) ||
291 (fToU16(amplitude, &, 2048, CS40L26_PWLE_LEVEL_MIN, CS40L26_PWLE_LEVEL_MAX) < 0) ||
292 (fToU16(frequency, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ) < 0)) {
293 ALOGE("%s: Invalid argument: %d, %f, %f", __func__, duration, amplitude, frequency);
294 return -ERANGE;
295 }
296 if (chirp) {
297 flags |= PWLE_CHIRP_BIT;
298 }
299 constructPwleSegment(delay, amp, freq, flags, 0 /*ignored*/);
300 return 0;
301 }
302
constructBrakingSegment(int duration,Braking brakingType)303 int constructBrakingSegment(int duration, Braking brakingType) {
304 HAPTICS_TRACE(" constructBrakingSegment(duration:%d, brakingType:%s)", duration,
305 toString(brakingType).c_str());
306 uint16_t delay = 0;
307 uint16_t freq = 0;
308 uint8_t flags = 0x00;
309 if (waveformType != WAVEFORM_PWLE) {
310 ALOGE("%s: Invalid type: %d", __func__, waveformType);
311 return -EDOM;
312 }
313 if (fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) {
314 ALOGE("%s: Invalid argument: %d", __func__, duration);
315 return -ERANGE;
316 }
317 fToU16(PWLE_FREQUENCY_MIN_HZ, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ);
318 if (static_cast<std::underlying_type<Braking>::type>(brakingType)) {
319 flags |= PWLE_BRAKE_BIT;
320 }
321
322 constructPwleSegment(delay, 0 /*ignored*/, freq, flags, 0 /*ignored*/);
323 return 0;
324 }
325
updateWLength(uint32_t totalDuration)326 int updateWLength(uint32_t totalDuration) {
327 HAPTICS_TRACE(" updateWLength(totalDuration:%u)", totalDuration);
328 uint8_t *f = front();
329 if (f == nullptr) {
330 ALOGE("%s: head does not exist!", __func__);
331 return -ENOMEM;
332 }
333 if (waveformType != WAVEFORM_PWLE) {
334 ALOGE("%s: Invalid type: %d", __func__, waveformType);
335 return -EDOM;
336 }
337 if (totalDuration > 0x7FFFF) {
338 ALOGE("%s: Invalid argument: %u", __func__, totalDuration);
339 return -EINVAL;
340 }
341 totalDuration *= 8; /* Unit: 0.125 ms (since wlength played @ 8kHz). */
342 totalDuration |=
343 WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */
344 *(f + 0) = (totalDuration >> 24) & 0xFF;
345 *(f + 1) = (totalDuration >> 16) & 0xFF;
346 *(f + 2) = (totalDuration >> 8) & 0xFF;
347 *(f + 3) = totalDuration & 0xFF;
348 return 0;
349 }
350
updateNSection(int segmentIdx)351 int updateNSection(int segmentIdx) {
352 HAPTICS_TRACE(" updateNSection(segmentIdx:%u)", segmentIdx);
353 uint8_t *f = front();
354 if (f == nullptr) {
355 ALOGE("%s: head does not exist!", __func__);
356 return -ENOMEM;
357 }
358
359 if (waveformType == WAVEFORM_COMPOSE) {
360 if (segmentIdx > COMPOSE_SIZE_MAX + 1 /*1st effect may have a delay*/) {
361 ALOGE("%s: Invalid argument: %d", __func__, segmentIdx);
362 return -EINVAL;
363 }
364 *(f + 2) = (0xFF & segmentIdx);
365 } else if (waveformType == WAVEFORM_PWLE) {
366 if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
367 ALOGE("%s: Invalid argument: %d", __func__, segmentIdx);
368 return -EINVAL;
369 }
370 *(f + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */
371 *(f + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */
372 } else {
373 ALOGE("%s: Invalid type: %d", __func__, waveformType);
374 return -EDOM;
375 }
376
377 return 0;
378 }
379 };
380
381 // Discrete points of frequency:max_level pairs around resonant(145Hz default) frequency
382 // Initialize the actuator LUXSHARE_ICT_081545 limits to 0.447 and others 1.0
383 #if defined(LUXSHARE_ICT_081545)
384 static std::map<float, float> discretePwleMaxLevels = {
385 {120.0, 0.447}, {130.0, 0.346}, {140.0, 0.156}, {145.0, 0.1},
386 {150.0, 0.167}, {160.0, 0.391}, {170.0, 0.447}};
387 std::vector<float> pwleMaxLevelLimitMap(PWLE_BW_MAP_SIZE, 0.447);
388 #else
389 static std::map<float, float> discretePwleMaxLevels = {};
390 std::vector<float> pwleMaxLevelLimitMap(PWLE_BW_MAP_SIZE, 1.0);
391 #endif
392
redcToFloat(std::string * caldata)393 static float redcToFloat(std::string *caldata) {
394 return static_cast<float>(std::stoul(*caldata, nullptr, 16)) / (1 << Q15_BIT_SHIFT);
395 }
396
Vibrator(std::unique_ptr<HwApi> hwapi,std::unique_ptr<HwCal> hwcal,std::unique_ptr<StatsApi> statsapi)397 Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal,
398 std::unique_ptr<StatsApi> statsapi)
399 : mHwApi(std::move(hwapi)),
400 mHwCal(std::move(hwcal)),
401 mStatsApi(std::move(statsapi)),
402 mAsyncHandle(std::async([] {})) {
403 int32_t longFrequencyShift;
404 std::string caldata{8, '0'};
405 uint32_t calVer;
406 const std::string INPUT_EVENT_NAME = std::getenv("INPUT_EVENT_NAME") ?: "";
407
408 mFfEffects.resize(WAVEFORM_MAX_INDEX);
409 mEffectDurations.resize(WAVEFORM_MAX_INDEX);
410 mEffectDurations = {
411 1000, 100, 12, 1000, 300, 130, 150, 500, 100, 5, 12, 1000, 1000, 1000,
412 }; /* 11+3 waveforms. The duration must < UINT16_MAX */
413 mEffectCustomData.reserve(WAVEFORM_MAX_INDEX);
414
415 uint8_t effectIndex;
416 uint16_t numBytes = 0;
417 for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) {
418 if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
419 /* Initialize physical waveforms. */
420 mEffectCustomData.push_back({RAM_WVFRM_BANK, effectIndex});
421 mFfEffects[effectIndex] = {
422 .type = FF_PERIODIC,
423 .id = -1,
424 .replay.length = static_cast<uint16_t>(mEffectDurations[effectIndex]),
425 .u.periodic.waveform = FF_CUSTOM,
426 .u.periodic.custom_data = mEffectCustomData[effectIndex].data(),
427 .u.periodic.custom_len =
428 static_cast<uint32_t>(mEffectCustomData[effectIndex].size()),
429 };
430 // Bypass the waveform update due to different input name
431 if (INPUT_EVENT_NAME.find("cs40l26") != std::string::npos) {
432 if (!mHwApi->setFFEffect(
433 &mFfEffects[effectIndex],
434 static_cast<uint16_t>(mFfEffects[effectIndex].replay.length))) {
435 mStatsApi->logError(kHwApiError);
436 ALOGE("Failed upload effect %d (%d): %s", effectIndex, errno, strerror(errno));
437 }
438 }
439 if (mFfEffects[effectIndex].id != effectIndex) {
440 ALOGW("Unexpected effect index: %d -> %d", effectIndex, mFfEffects[effectIndex].id);
441 }
442 } else {
443 /* Initiate placeholders for OWT effects. */
444 numBytes = effectIndex == WAVEFORM_COMPOSE ? FF_CUSTOM_DATA_LEN_MAX_COMP
445 : FF_CUSTOM_DATA_LEN_MAX_PWLE;
446 std::vector<int16_t> tempVec(numBytes, 0);
447 mEffectCustomData.push_back(std::move(tempVec));
448 mFfEffects[effectIndex] = {
449 .type = FF_PERIODIC,
450 .id = -1,
451 .replay.length = 0,
452 .u.periodic.waveform = FF_CUSTOM,
453 .u.periodic.custom_data = mEffectCustomData[effectIndex].data(),
454 .u.periodic.custom_len = 0,
455 };
456 }
457 }
458
459 if (mHwCal->getF0(&caldata)) {
460 mHwApi->setF0(caldata);
461 mResonantFrequency =
462 static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q14_BIT_SHIFT);
463 } else {
464 mStatsApi->logError(kHwCalError);
465 ALOGE("Failed to get resonant frequency (%d): %s, using default resonant HZ: %f", errno,
466 strerror(errno), RESONANT_FREQUENCY_DEFAULT);
467 mResonantFrequency = RESONANT_FREQUENCY_DEFAULT;
468 }
469 if (mHwCal->getRedc(&caldata)) {
470 mHwApi->setRedc(caldata);
471 mRedc = redcToFloat(&caldata);
472 }
473 if (mHwCal->getQ(&caldata)) {
474 mHwApi->setQ(caldata);
475 }
476
477 mHwCal->getLongFrequencyShift(&longFrequencyShift);
478 if (longFrequencyShift > 0) {
479 mF0Offset = longFrequencyShift * std::pow(2, 14);
480 } else if (longFrequencyShift < 0) {
481 mF0Offset = std::pow(2, 24) - std::abs(longFrequencyShift) * std::pow(2, 14);
482 } else {
483 mF0Offset = 0;
484 }
485
486 mHwCal->getVersion(&calVer);
487 if (calVer == 2) {
488 mHwCal->getTickVolLevels(&mTickEffectVol);
489 mHwCal->getClickVolLevels(&mClickEffectVol);
490 mHwCal->getLongVolLevels(&mLongEffectVol);
491 } else {
492 ALOGD("Unsupported calibration version: %u!", calVer);
493 }
494 HAPTICS_TRACE("Vibrator(hwapi, hwcal:%u)", calVer);
495
496 mHwApi->setF0CompEnable(mHwCal->isF0CompEnabled());
497 mHwApi->setRedcCompEnable(mHwCal->isRedcCompEnabled());
498
499 mIsUnderExternalControl = false;
500
501 mIsChirpEnabled = mHwCal->isChirpEnabled();
502
503 mHwCal->getSupportedPrimitives(&mSupportedPrimitivesBits);
504 if (mSupportedPrimitivesBits > 0) {
505 for (auto e : defaultSupportedPrimitives) {
506 if (mSupportedPrimitivesBits & (1 << uint32_t(e))) {
507 mSupportedPrimitives.emplace_back(e);
508 }
509 }
510 } else {
511 for (auto e : defaultSupportedPrimitives) {
512 mSupportedPrimitivesBits |= (1 << uint32_t(e));
513 }
514 mSupportedPrimitives = defaultSupportedPrimitives;
515 }
516
517 mHwApi->setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US);
518
519 createPwleMaxLevelLimitMap();
520 createBandwidthAmplitudeMap();
521
522 // We need to do this until it's supported through WISCE
523 mHwApi->enableDbc();
524
525 #ifdef ADAPTIVE_HAPTICS_V1
526 updateContext();
527 #endif /*ADAPTIVE_HAPTICS_V1*/
528 }
529
getCapabilities(int32_t * _aidl_return)530 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) {
531 HAPTICS_TRACE("getCapabilities(_aidl_return)");
532 ATRACE_NAME("Vibrator::getCapabilities");
533
534 int32_t ret = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
535 IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
536 IVibrator::CAP_GET_Q_FACTOR;
537 if (hasHapticAlsaDevice()) {
538 ret |= IVibrator::CAP_EXTERNAL_CONTROL;
539 } else {
540 mStatsApi->logError(kAlsaFailError);
541 ALOGE("No haptics ALSA device");
542 }
543 if (mHwApi->hasOwtFreeSpace()) {
544 ret |= IVibrator::CAP_COMPOSE_EFFECTS;
545 if (mIsChirpEnabled) {
546 ret |= IVibrator::CAP_FREQUENCY_CONTROL | IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
547 }
548 }
549 *_aidl_return = ret;
550 return ndk::ScopedAStatus::ok();
551 }
552
off()553 ndk::ScopedAStatus Vibrator::off() {
554 HAPTICS_TRACE("off()");
555 ATRACE_NAME("Vibrator::off");
556 bool ret{true};
557 const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
558
559 const auto startTime = std::chrono::system_clock::now();
560 const auto endTime = startTime + std::chrono::milliseconds(POLLING_TIMEOUT);
561 auto now = startTime;
562 while (halState == ISSUED && now <= endTime) {
563 std::this_thread::sleep_for(std::chrono::milliseconds(1));
564 now = std::chrono::system_clock::now();
565 }
566 if (halState == ISSUED && now > endTime) {
567 ALOGE("Timeout waiting for the actuator activation! (%d ms)", POLLING_TIMEOUT);
568 } else if (halState == PLAYING) {
569 ALOGD("Took %lld ms to wait for the actuator activation.",
570 std::chrono::duration_cast<std::chrono::milliseconds>(now - startTime).count());
571 }
572
573 if (mActiveId >= 0) {
574 /* Stop the active effect. */
575 if (!mHwApi->setFFPlay(mActiveId, false)) {
576 mStatsApi->logError(kHwApiError);
577 ALOGE("Failed to stop effect %d (%d): %s", mActiveId, errno, strerror(errno));
578 ret = false;
579 }
580 halState = STOPPED;
581
582 if ((mActiveId >= WAVEFORM_MAX_PHYSICAL_INDEX) &&
583 (!mHwApi->eraseOwtEffect(mActiveId, &mFfEffects))) {
584 mStatsApi->logError(kHwApiError);
585 ALOGE("Failed to clean up the composed effect %d", mActiveId);
586 ret = false;
587 }
588 } else {
589 ALOGV("Vibrator is already off");
590 }
591
592 mActiveId = -1;
593 setGlobalAmplitude(false);
594 if (mF0Offset) {
595 mHwApi->setF0Offset(0);
596 }
597 halState = RESTORED;
598
599 if (ret) {
600 return ndk::ScopedAStatus::ok();
601 } else {
602 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
603 }
604 }
605
on(int32_t timeoutMs,const std::shared_ptr<IVibratorCallback> & callback)606 ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
607 const std::shared_ptr<IVibratorCallback> &callback) {
608 ATRACE_NAME(StringPrintf("Vibrator::on %dms", timeoutMs).c_str());
609 HAPTICS_TRACE("on(timeoutMs:%d, callback)", timeoutMs);
610
611 mStatsApi->logLatencyStart(kWaveformEffectLatency);
612 if (timeoutMs > MAX_TIME_MS) {
613 mStatsApi->logError(kBadTimeoutError);
614 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
615 }
616 const uint16_t index = (timeoutMs < WAVEFORM_LONG_VIBRATION_THRESHOLD_MS)
617 ? WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX
618 : WAVEFORM_LONG_VIBRATION_EFFECT_INDEX;
619 if (MAX_COLD_START_LATENCY_MS <= MAX_TIME_MS - timeoutMs) {
620 timeoutMs += MAX_COLD_START_LATENCY_MS;
621 }
622 setGlobalAmplitude(true);
623 if (mF0Offset) {
624 mHwApi->setF0Offset(mF0Offset);
625 }
626
627 mStatsApi->logWaveform(index, timeoutMs);
628 return on(timeoutMs, index, nullptr /*ignored*/, callback);
629 }
630
perform(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * _aidl_return)631 ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
632 const std::shared_ptr<IVibratorCallback> &callback,
633 int32_t *_aidl_return) {
634 ATRACE_NAME(StringPrintf("Vibrator::perform %s,%s", toString(effect).c_str(),
635 toString(strength).c_str())
636 .c_str());
637 HAPTICS_TRACE("perform(effect:%s, strength:%s, callback, _aidl_return)",
638 toString(effect).c_str(), toString(strength).c_str());
639
640 mStatsApi->logLatencyStart(kPrebakedEffectLatency);
641
642 return performEffect(effect, strength, callback, _aidl_return);
643 }
644
getSupportedEffects(std::vector<Effect> * _aidl_return)645 ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect> *_aidl_return) {
646 HAPTICS_TRACE("getSupportedEffects(_aidl_return)");
647 *_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK,
648 Effect::DOUBLE_CLICK};
649 return ndk::ScopedAStatus::ok();
650 }
651
setAmplitude(float amplitude)652 ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
653 HAPTICS_TRACE("setAmplitude(amplitude:%f)", amplitude);
654 ATRACE_NAME("Vibrator::setAmplitude");
655 if (amplitude <= 0.0f || amplitude > 1.0f) {
656 mStatsApi->logError(kBadAmplitudeError);
657 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
658 }
659
660 mLongEffectScale = amplitude;
661 if (!isUnderExternalControl()) {
662 return setGlobalAmplitude(true);
663 } else {
664 mStatsApi->logError(kUnsupportedOpError);
665 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
666 }
667 }
668
setExternalControl(bool enabled)669 ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
670 HAPTICS_TRACE("setExternalControl(enabled:%u)", enabled);
671 ATRACE_NAME("Vibrator::setExternalControl");
672 setGlobalAmplitude(enabled);
673
674 if (mHasHapticAlsaDevice || mConfigHapticAlsaDeviceDone || hasHapticAlsaDevice()) {
675 if (!mHwApi->setHapticPcmAmp(&mHapticPcm, enabled, mCard, mDevice)) {
676 mStatsApi->logError(kHwApiError);
677 ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"), mDevice);
678 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
679 }
680 } else {
681 mStatsApi->logError(kAlsaFailError);
682 ALOGE("No haptics ALSA device");
683 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
684 }
685
686 mIsUnderExternalControl = enabled;
687 return ndk::ScopedAStatus::ok();
688 }
689
getCompositionDelayMax(int32_t * maxDelayMs)690 ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t *maxDelayMs) {
691 HAPTICS_TRACE("getCompositionDelayMax(maxDelayMs)");
692 ATRACE_NAME("Vibrator::getCompositionDelayMax");
693 *maxDelayMs = COMPOSE_DELAY_MAX_MS;
694 return ndk::ScopedAStatus::ok();
695 }
696
getCompositionSizeMax(int32_t * maxSize)697 ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t *maxSize) {
698 HAPTICS_TRACE("getCompositionSizeMax(maxSize)");
699 ATRACE_NAME("Vibrator::getCompositionSizeMax");
700 *maxSize = COMPOSE_SIZE_MAX;
701 return ndk::ScopedAStatus::ok();
702 }
703
getSupportedPrimitives(std::vector<CompositePrimitive> * supported)704 ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive> *supported) {
705 HAPTICS_TRACE("getSupportedPrimitives(supported)");
706 *supported = mSupportedPrimitives;
707 return ndk::ScopedAStatus::ok();
708 }
709
getPrimitiveDuration(CompositePrimitive primitive,int32_t * durationMs)710 ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
711 int32_t *durationMs) {
712 HAPTICS_TRACE("getPrimitiveDuration(primitive:%s, durationMs)", toString(primitive).c_str());
713 ndk::ScopedAStatus status;
714 uint32_t effectIndex;
715 if (primitive != CompositePrimitive::NOOP) {
716 status = getPrimitiveDetails(primitive, &effectIndex);
717 if (!status.isOk()) {
718 return status;
719 }
720
721 *durationMs = mEffectDurations[effectIndex];
722 } else {
723 *durationMs = 0;
724 }
725 return ndk::ScopedAStatus::ok();
726 }
727
compose(const std::vector<CompositeEffect> & composite,const std::shared_ptr<IVibratorCallback> & callback)728 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> &composite,
729 const std::shared_ptr<IVibratorCallback> &callback) {
730 ATRACE_NAME(StringPrintf("Vibrator::compose size=%zu", composite.size()).c_str());
731 HAPTICS_TRACE("compose(composite, callback)");
732 uint16_t size;
733 uint16_t nextEffectDelay;
734 uint16_t totalDuration = 0;
735
736 mStatsApi->logLatencyStart(kCompositionEffectLatency);
737
738 if (composite.size() > COMPOSE_SIZE_MAX || composite.empty()) {
739 ALOGE("%s: Invalid size", __func__);
740 mStatsApi->logError(kBadCompositeError);
741 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
742 }
743
744 /* Check if there is a wait before the first effect. */
745 nextEffectDelay = composite.front().delayMs;
746 totalDuration += nextEffectDelay;
747 if (nextEffectDelay > COMPOSE_DELAY_MAX_MS || nextEffectDelay < 0) {
748 ALOGE("%s: Invalid delay %u", __func__, nextEffectDelay);
749 mStatsApi->logError(kBadCompositeError);
750 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
751 } else if (nextEffectDelay > 0) {
752 size = composite.size() + 1;
753 } else {
754 size = composite.size();
755 }
756
757 DspMemChunk ch(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP);
758 const uint8_t header_count = ch.size();
759
760 /* Insert 1 section for a wait before the first effect. */
761 if (nextEffectDelay) {
762 ch.constructComposeSegment(0 /*amplitude*/, 0 /*index*/, 0 /*repeat*/, 0 /*flags*/,
763 nextEffectDelay /*delay*/);
764 }
765
766 for (uint32_t i_curr = 0, i_next = 1; i_curr < composite.size(); i_curr++, i_next++) {
767 auto &e_curr = composite[i_curr];
768 uint32_t effectIndex = 0;
769 uint32_t effectVolLevel = 0;
770 if (e_curr.scale < 0.0f || e_curr.scale > 1.0f) {
771 ALOGE("%s: #%u: Invalid scale %f", __func__, i_curr, e_curr.scale);
772 mStatsApi->logError(kBadCompositeError);
773 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
774 }
775
776 if (e_curr.primitive != CompositePrimitive::NOOP) {
777 ndk::ScopedAStatus status;
778 status = getPrimitiveDetails(e_curr.primitive, &effectIndex);
779 if (!status.isOk()) {
780 return status;
781 }
782 effectVolLevel = intensityToVolLevel(e_curr.scale, effectIndex);
783 totalDuration += mEffectDurations[effectIndex];
784 }
785
786 /* Fetch the next composite effect delay and fill into the current section */
787 nextEffectDelay = 0;
788 if (i_next < composite.size()) {
789 auto &e_next = composite[i_next];
790 int32_t delay = e_next.delayMs;
791
792 if (delay > COMPOSE_DELAY_MAX_MS || delay < 0) {
793 ALOGE("%s: #%u: Invalid delay %d", __func__, i_next, delay);
794 mStatsApi->logError(kBadCompositeError);
795 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
796 }
797 nextEffectDelay = delay;
798 totalDuration += delay;
799 }
800
801 if (effectIndex == 0 && nextEffectDelay == 0) {
802 ALOGE("%s: #%u: Invalid results", __func__, i_curr);
803 mStatsApi->logError(kBadCompositeError);
804 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
805 }
806 mStatsApi->logPrimitive(effectIndex);
807 ch.constructComposeSegment(effectVolLevel, effectIndex, 0 /*repeat*/, 0 /*flags*/,
808 nextEffectDelay /*delay*/);
809 }
810
811 ch.flush();
812 if (ch.updateNSection(size) < 0) {
813 mStatsApi->logError(kComposeFailError);
814 ALOGE("%s: Failed to update the section count", __func__);
815 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
816 }
817 if (header_count == ch.size()) {
818 ALOGE("%s: Failed to append effects", __func__);
819 mStatsApi->logError(kComposeFailError);
820 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
821 } else {
822 mFfEffects[WAVEFORM_COMPOSE].replay.length = totalDuration;
823 return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch,
824 callback);
825 }
826 }
827
on(uint32_t timeoutMs,uint32_t effectIndex,const DspMemChunk * ch,const std::shared_ptr<IVibratorCallback> & callback)828 ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, const DspMemChunk *ch,
829 const std::shared_ptr<IVibratorCallback> &callback) {
830 HAPTICS_TRACE("on(timeoutMs:%u, effectIndex:%u, ch, callback)", timeoutMs, effectIndex);
831 ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
832
833 if (effectIndex >= FF_MAX_EFFECTS) {
834 mStatsApi->logError(kBadEffectError);
835 ALOGE("Invalid waveform index %d", effectIndex);
836 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
837 }
838 if (mAsyncHandle.wait_for(ASYNC_COMPLETION_TIMEOUT) != std::future_status::ready) {
839 mStatsApi->logError(kAsyncFailError);
840 ALOGE("Previous vibration pending: prev: %d, curr: %d", mActiveId, effectIndex);
841 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
842 }
843
844 if (ch) {
845 /* Upload OWT effect. */
846 if (ch->front() == nullptr) {
847 mStatsApi->logError(kBadCompositeError);
848 ALOGE("Invalid OWT bank");
849 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
850 }
851
852 if (ch->type() != WAVEFORM_PWLE && ch->type() != WAVEFORM_COMPOSE) {
853 mStatsApi->logError(kBadCompositeError);
854 ALOGE("Invalid OWT type");
855 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
856 }
857 effectIndex = ch->type();
858
859 uint32_t freeBytes;
860 mHwApi->getOwtFreeSpace(&freeBytes);
861 if (ch->size() > freeBytes) {
862 mStatsApi->logError(kBadCompositeError);
863 ALOGE("Invalid OWT length: Effect %d: %zu > %d!", effectIndex, ch->size(), freeBytes);
864 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
865 }
866 int errorStatus;
867 if (!mHwApi->uploadOwtEffect(ch->front(), ch->size(), &mFfEffects[effectIndex],
868 &effectIndex, &errorStatus)) {
869 mStatsApi->logError(kHwApiError);
870 ALOGE("Invalid uploadOwtEffect");
871 return ndk::ScopedAStatus::fromExceptionCode(errorStatus);
872 }
873
874 } else if (effectIndex == WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX ||
875 effectIndex == WAVEFORM_LONG_VIBRATION_EFFECT_INDEX) {
876 /* Update duration for long/short vibration. */
877 mFfEffects[effectIndex].replay.length = static_cast<uint16_t>(timeoutMs);
878 if (!mHwApi->setFFEffect(&mFfEffects[effectIndex], static_cast<uint16_t>(timeoutMs))) {
879 mStatsApi->logError(kHwApiError);
880 ALOGE("Failed to edit effect %d (%d): %s", effectIndex, errno, strerror(errno));
881 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
882 }
883 }
884
885 const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
886 mActiveId = effectIndex;
887 /* Play the event now. */
888 mStatsApi->logLatencyEnd();
889 if (!mHwApi->setFFPlay(effectIndex, true)) {
890 mStatsApi->logError(kHwApiError);
891 ALOGE("Failed to play effect %d (%d): %s", effectIndex, errno, strerror(errno));
892 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
893 }
894 halState = ISSUED;
895
896 mAsyncHandle = std::async(&Vibrator::waitForComplete, this, callback);
897 return ndk::ScopedAStatus::ok();
898 }
899
amplitudeToScale(float amplitude,float maximum,bool scalable)900 uint16_t Vibrator::amplitudeToScale(float amplitude, float maximum, bool scalable) {
901 HAPTICS_TRACE("amplitudeToScale(amplitude:%f, maximum:%f, scalable:%d)", amplitude, maximum,
902 scalable ? 1 : 0);
903 float ratio = 100; /* Unit: % */
904
905 if (maximum != 0)
906 ratio = amplitude / maximum * 100;
907
908 if (maximum == 0 || ratio > 100)
909 ratio = 100;
910
911 #ifdef ADAPTIVE_HAPTICS_V1
912 if (scalable && mContextEnable && mContextListener) {
913 uint32_t now = CapoDetector::getCurrentTimeInMs();
914 uint32_t last_played = mLastEffectPlayedTime;
915 uint32_t lastFaceUpTime = 0;
916 uint8_t carriedPosition = 0;
917 float context_scale = 1.0;
918 bool device_face_up = false;
919 float pre_scaled_ratio = ratio;
920 mLastEffectPlayedTime = now;
921
922 mContextListener->getCarriedPositionInfo(&carriedPosition, &lastFaceUpTime);
923 device_face_up = carriedPosition == capo::PositionType::ON_TABLE_FACE_UP;
924
925 ALOGD("Vibrator Now: %u, Last: %u, ScaleTime: %u, Since? %d", now, lastFaceUpTime,
926 mScaleTime, (now < lastFaceUpTime + mScaleTime));
927 /* If the device is face-up or within the fade scaling range, find new scaling factor */
928 if (device_face_up || now < lastFaceUpTime + mScaleTime) {
929 /* Device is face-up, so we will scale it down. Start with highest scaling factor */
930 context_scale = mScalingFactor <= 100 ? static_cast<float>(mScalingFactor) / 100 : 1.0;
931 if (mFadeEnable && mScaleTime > 0 && (context_scale < 1.0) &&
932 (now < lastFaceUpTime + mScaleTime) && !device_face_up) {
933 float fade_scale =
934 static_cast<float>(now - lastFaceUpTime) / static_cast<float>(mScaleTime);
935 context_scale += ((1.0 - context_scale) * fade_scale);
936 ALOGD("Vibrator fade scale applied: %f", fade_scale);
937 }
938 ratio *= context_scale;
939 ALOGD("Vibrator adjusting for face-up: pre: %f, post: %f", std::round(pre_scaled_ratio),
940 std::round(ratio));
941 }
942
943 /* If we haven't played an effect within the cooldown time, save the scaling factor */
944 if ((now - last_played) > mScaleCooldown) {
945 ALOGD("Vibrator updating lastplayed scale, old: %f, new: %f", mLastPlayedScale,
946 context_scale);
947 mLastPlayedScale = context_scale;
948 } else {
949 /* Override the scale to match previously played scale */
950 ratio = mLastPlayedScale * pre_scaled_ratio;
951 ALOGD("Vibrator repeating last scale: %f, new ratio: %f, duration since last: %u",
952 mLastPlayedScale, ratio, (now - last_played));
953 }
954 }
955 #else
956 // Suppress compiler warning
957 (void)scalable;
958 #endif /*ADAPTIVE_HAPTICS_V1*/
959
960 return std::round(ratio);
961 }
962
updateContext()963 void Vibrator::updateContext() {
964 mContextEnable = mHwApi->getContextEnable();
965 if (mContextEnable && !mContextEnabledPreviously) {
966 mContextListener = CapoDetector::start();
967 if (mContextListener == nullptr) {
968 ALOGE("%s, CapoDetector failed to start", __func__);
969 } else {
970 mFadeEnable = mHwApi->getContextFadeEnable();
971 mScalingFactor = mHwApi->getContextScale();
972 mScaleTime = mHwApi->getContextSettlingTime();
973 mScaleCooldown = mHwApi->getContextCooldownTime();
974 ALOGD("%s, CapoDetector started successfully! NanoAppID: 0x%x, Scaling Factor: %d, "
975 "Scaling Time: %d, Cooldown Time: %d",
976 __func__, (uint32_t)mContextListener->getNanoppAppId(), mScalingFactor,
977 mScaleTime, mScaleCooldown);
978
979 /* We no longer need to use this path */
980 mContextEnabledPreviously = true;
981 }
982 }
983 }
984
setEffectAmplitude(float amplitude,float maximum,bool scalable)985 ndk::ScopedAStatus Vibrator::setEffectAmplitude(float amplitude, float maximum, bool scalable) {
986 HAPTICS_TRACE("setEffectAmplitude(amplitude:%f, maximum:%f, scalable:%d)", amplitude, maximum,
987 scalable ? 1 : 0);
988 uint16_t scale;
989
990 #ifdef ADAPTIVE_HAPTICS_V1
991 updateContext();
992 #endif /*ADAPTIVE_HAPTICS_V1*/
993
994 scale = amplitudeToScale(amplitude, maximum, scalable);
995
996 if (!mHwApi->setFFGain(scale)) {
997 mStatsApi->logError(kHwApiError);
998 ALOGE("Failed to set the gain to %u (%d): %s", scale, errno, strerror(errno));
999 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1000 }
1001 return ndk::ScopedAStatus::ok();
1002 }
1003
setGlobalAmplitude(bool set)1004 ndk::ScopedAStatus Vibrator::setGlobalAmplitude(bool set) {
1005 HAPTICS_TRACE("setGlobalAmplitude(set:%u)", set);
1006 uint8_t amplitude = set ? roundf(mLongEffectScale * mLongEffectVol[1]) : VOLTAGE_SCALE_MAX;
1007 if (!set) {
1008 mLongEffectScale = 1.0; // Reset the scale for the later new effect.
1009 }
1010 return setEffectAmplitude(amplitude, VOLTAGE_SCALE_MAX, set);
1011 }
1012
getSupportedAlwaysOnEffects(std::vector<Effect> *)1013 ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect> * /*_aidl_return*/) {
1014 mStatsApi->logError(kUnsupportedOpError);
1015 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1016 }
1017
alwaysOnEnable(int32_t,Effect,EffectStrength)1018 ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t /*id*/, Effect /*effect*/,
1019 EffectStrength /*strength*/) {
1020 mStatsApi->logError(kUnsupportedOpError);
1021 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1022 }
alwaysOnDisable(int32_t)1023 ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t /*id*/) {
1024 mStatsApi->logError(kUnsupportedOpError);
1025 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1026 }
1027
getResonantFrequency(float * resonantFreqHz)1028 ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
1029 HAPTICS_TRACE("getResonantFrequency(resonantFreqHz)");
1030 *resonantFreqHz = mResonantFrequency;
1031
1032 return ndk::ScopedAStatus::ok();
1033 }
1034
getQFactor(float * qFactor)1035 ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
1036 HAPTICS_TRACE("getQFactor(qFactor)");
1037 std::string caldata{8, '0'};
1038 if (!mHwCal->getQ(&caldata)) {
1039 mStatsApi->logError(kHwCalError);
1040 ALOGE("Failed to get q factor (%d): %s", errno, strerror(errno));
1041 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1042 }
1043 *qFactor = static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q16_BIT_SHIFT);
1044
1045 return ndk::ScopedAStatus::ok();
1046 }
1047
getFrequencyResolution(float * freqResolutionHz)1048 ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
1049 HAPTICS_TRACE("getFrequencyResolution(freqResolutionHz)");
1050 int32_t capabilities;
1051 Vibrator::getCapabilities(&capabilities);
1052 if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1053 *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
1054 return ndk::ScopedAStatus::ok();
1055 } else {
1056 mStatsApi->logError(kUnsupportedOpError);
1057 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1058 }
1059 }
1060
getFrequencyMinimum(float * freqMinimumHz)1061 ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
1062 HAPTICS_TRACE("getFrequencyMinimum(freqMinimumHz)");
1063 int32_t capabilities;
1064 Vibrator::getCapabilities(&capabilities);
1065 if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1066 *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
1067 return ndk::ScopedAStatus::ok();
1068 } else {
1069 mStatsApi->logError(kUnsupportedOpError);
1070 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1071 }
1072 }
1073
createPwleMaxLevelLimitMap()1074 void Vibrator::createPwleMaxLevelLimitMap() {
1075 int32_t capabilities;
1076 Vibrator::getCapabilities(&capabilities);
1077 if (!(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
1078 mStatsApi->logError(kUnsupportedOpError);
1079 ALOGE("Frequency control not support.");
1080 return;
1081 }
1082
1083 if (discretePwleMaxLevels.empty()) {
1084 mStatsApi->logError(kInitError);
1085 ALOGE("Discrete PWLE max level maps are empty.");
1086 return;
1087 }
1088
1089 int32_t pwleMaxLevelLimitMapIdx = 0;
1090 std::map<float, float>::iterator itr0 = discretePwleMaxLevels.begin();
1091 if (discretePwleMaxLevels.size() == 1) {
1092 ALOGD("Discrete PWLE max level map size is 1");
1093 pwleMaxLevelLimitMapIdx =
1094 (itr0->first - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ;
1095 pwleMaxLevelLimitMap[pwleMaxLevelLimitMapIdx] = itr0->second;
1096 return;
1097 }
1098
1099 auto itr1 = std::next(itr0, 1);
1100
1101 while (itr1 != discretePwleMaxLevels.end()) {
1102 float x0 = itr0->first;
1103 float y0 = itr0->second;
1104 float x1 = itr1->first;
1105 float y1 = itr1->second;
1106 const float ratioOfXY = ((y1 - y0) / (x1 - x0));
1107 pwleMaxLevelLimitMapIdx =
1108 (itr0->first - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ;
1109
1110 // FixLater: avoid floating point loop counters
1111 // NOLINTBEGIN(clang-analyzer-security.FloatLoopCounter,cert-flp30-c)
1112 for (float xp = x0; xp < (x1 + PWLE_FREQUENCY_RESOLUTION_HZ);
1113 xp += PWLE_FREQUENCY_RESOLUTION_HZ) {
1114 // NOLINTEND(clang-analyzer-security.FloatLoopCounter,cert-flp30-c)
1115 float yp = y0 + ratioOfXY * (xp - x0);
1116
1117 pwleMaxLevelLimitMap[pwleMaxLevelLimitMapIdx++] = yp;
1118 }
1119
1120 itr0++;
1121 itr1++;
1122 }
1123 }
1124
createBandwidthAmplitudeMap()1125 void Vibrator::createBandwidthAmplitudeMap() {
1126 // Use constant Q Factor of 10 from HW's suggestion
1127 const float qFactor = 10.0f;
1128 const float blSys = 1.1f;
1129 const float gravity = 9.81f;
1130 const float maxVoltage = 11.0f;
1131 float deviceMass = 0, locCoeff = 0;
1132
1133 mHwCal->getDeviceMass(&deviceMass);
1134 mHwCal->getLocCoeff(&locCoeff);
1135 if (!deviceMass || !locCoeff) {
1136 mStatsApi->logError(kInitError);
1137 ALOGE("Failed to get Device Mass: %f and Loc Coeff: %f", deviceMass, locCoeff);
1138 return;
1139 }
1140
1141 // Resistance value need to be retrieved from calibration file
1142 if (mRedc == 0.0) {
1143 std::string caldata{8, '0'};
1144 if (mHwCal->getRedc(&caldata)) {
1145 mHwApi->setRedc(caldata);
1146 mRedc = redcToFloat(&caldata);
1147 } else {
1148 mStatsApi->logError(kHwCalError);
1149 ALOGE("Failed to get resistance value from calibration file");
1150 return;
1151 }
1152 }
1153
1154 std::vector<float> bandwidthAmplitudeMap(PWLE_BW_MAP_SIZE, 1.0);
1155
1156 const float wnSys = mResonantFrequency * 2 * M_PI;
1157 const float powWnSys = pow(wnSys, 2);
1158 const float var2Para = wnSys / qFactor;
1159
1160 float frequencyHz = PWLE_FREQUENCY_MIN_HZ;
1161 float frequencyRadians = 0.0f;
1162 float vLevel = 0.4473f;
1163 float vSys = (mLongEffectVol[1] / 100.0) * maxVoltage * vLevel;
1164 float maxAsys = 0;
1165 const float amplitudeSysPara = blSys * locCoeff / mRedc / deviceMass;
1166
1167 for (int i = 0; i < PWLE_BW_MAP_SIZE; i++) {
1168 frequencyRadians = frequencyHz * 2 * M_PI;
1169 vLevel = pwleMaxLevelLimitMap[i];
1170 vSys = (mLongEffectVol[1] / 100.0) * maxVoltage * vLevel;
1171
1172 float var1 = pow((powWnSys - pow(frequencyRadians, 2)), 2);
1173 float var2 = pow((var2Para * frequencyRadians), 2);
1174
1175 float psysAbs = sqrt(var1 + var2);
1176 // The equation and all related details can be found in the bug
1177 float amplitudeSys =
1178 (vSys * amplitudeSysPara) * pow(frequencyRadians, 2) / psysAbs / gravity;
1179 // Record the maximum acceleration for the next for loop
1180 if (amplitudeSys > maxAsys)
1181 maxAsys = amplitudeSys;
1182
1183 bandwidthAmplitudeMap[i] = amplitudeSys;
1184 frequencyHz += PWLE_FREQUENCY_RESOLUTION_HZ;
1185 }
1186 // Scaled the map between 0 and 1.0
1187 if (maxAsys > 0) {
1188 for (int j = 0; j < PWLE_BW_MAP_SIZE; j++) {
1189 bandwidthAmplitudeMap[j] =
1190 std::floor((bandwidthAmplitudeMap[j] / maxAsys) * 1000) / 1000;
1191 }
1192 mBandwidthAmplitudeMap = bandwidthAmplitudeMap;
1193 mCreateBandwidthAmplitudeMapDone = true;
1194 } else {
1195 mCreateBandwidthAmplitudeMapDone = false;
1196 }
1197 }
1198
getBandwidthAmplitudeMap(std::vector<float> * _aidl_return)1199 ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
1200 HAPTICS_TRACE("getBandwidthAmplitudeMap(_aidl_return)");
1201 int32_t capabilities;
1202 Vibrator::getCapabilities(&capabilities);
1203 if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1204 if (!mCreateBandwidthAmplitudeMapDone) {
1205 createPwleMaxLevelLimitMap();
1206 createBandwidthAmplitudeMap();
1207 }
1208 *_aidl_return = mBandwidthAmplitudeMap;
1209 return (!mBandwidthAmplitudeMap.empty())
1210 ? ndk::ScopedAStatus::ok()
1211 : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1212 } else {
1213 mStatsApi->logError(kUnsupportedOpError);
1214 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1215 }
1216 }
1217
getPwlePrimitiveDurationMax(int32_t * durationMs)1218 ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
1219 HAPTICS_TRACE("getPwlePrimitiveDurationMax(durationMs)");
1220 int32_t capabilities;
1221 Vibrator::getCapabilities(&capabilities);
1222 if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1223 *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
1224 return ndk::ScopedAStatus::ok();
1225 } else {
1226 mStatsApi->logError(kUnsupportedOpError);
1227 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1228 }
1229 }
1230
getPwleCompositionSizeMax(int32_t * maxSize)1231 ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
1232 HAPTICS_TRACE("getPwleCompositionSizeMax(maxSize)");
1233 int32_t capabilities;
1234 Vibrator::getCapabilities(&capabilities);
1235 if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1236 *maxSize = COMPOSE_PWLE_SIZE_MAX_DEFAULT;
1237 return ndk::ScopedAStatus::ok();
1238 } else {
1239 mStatsApi->logError(kUnsupportedOpError);
1240 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1241 }
1242 }
1243
getSupportedBraking(std::vector<Braking> * supported)1244 ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
1245 HAPTICS_TRACE("getSupportedBraking(supported)");
1246 int32_t capabilities;
1247 Vibrator::getCapabilities(&capabilities);
1248 if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1249 *supported = {
1250 Braking::NONE,
1251 };
1252 return ndk::ScopedAStatus::ok();
1253 } else {
1254 mStatsApi->logError(kUnsupportedOpError);
1255 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1256 }
1257 }
1258
resetPreviousEndAmplitudeEndFrequency(float * prevEndAmplitude,float * prevEndFrequency)1259 static void resetPreviousEndAmplitudeEndFrequency(float *prevEndAmplitude,
1260 float *prevEndFrequency) {
1261 HAPTICS_TRACE(" resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency)");
1262 const float reset = -1.0;
1263 *prevEndAmplitude = reset;
1264 *prevEndFrequency = reset;
1265 }
1266
incrementIndex(int * index)1267 static void incrementIndex(int *index) {
1268 *index += 1;
1269 }
1270
composePwle(const std::vector<PrimitivePwle> & composite,const std::shared_ptr<IVibratorCallback> & callback)1271 ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
1272 const std::shared_ptr<IVibratorCallback> &callback) {
1273 ATRACE_NAME(StringPrintf("Vibrator::composePwle size=%zu", composite.size()).c_str());
1274 HAPTICS_TRACE("composePwle(composite, callback)");
1275 int32_t capabilities;
1276
1277 mStatsApi->logLatencyStart(kPwleEffectLatency);
1278
1279 Vibrator::getCapabilities(&capabilities);
1280 if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) == 0) {
1281 ALOGE("%s: Not supported", __func__);
1282 mStatsApi->logError(kUnsupportedOpError);
1283 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1284 }
1285
1286 if (composite.empty() || composite.size() > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
1287 ALOGE("%s: Invalid size", __func__);
1288 mStatsApi->logError(kBadCompositeError);
1289 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1290 }
1291
1292 std::vector<Braking> supported;
1293 Vibrator::getSupportedBraking(&supported);
1294 bool isClabSupported =
1295 std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
1296
1297 int segmentIdx = 0;
1298 uint32_t totalDuration = 0;
1299 float prevEndAmplitude;
1300 float prevEndFrequency;
1301 resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
1302 DspMemChunk ch(WAVEFORM_PWLE, FF_CUSTOM_DATA_LEN_MAX_PWLE);
1303 bool chirp = false;
1304 uint16_t c = 0;
1305
1306 for (auto &e : composite) {
1307 switch (e.getTag()) {
1308 case PrimitivePwle::active: {
1309 auto active = e.get<PrimitivePwle::active>();
1310 if (active.duration < 0 ||
1311 active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
1312 mStatsApi->logError(kBadPrimitiveError);
1313 ALOGE("%s: #%u: active: Invalid duration %d", __func__, c, active.duration);
1314 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1315 }
1316 if (active.startAmplitude < PWLE_LEVEL_MIN ||
1317 active.startAmplitude > PWLE_LEVEL_MAX ||
1318 active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
1319 mStatsApi->logError(kBadPrimitiveError);
1320 ALOGE("%s: #%u: active: Invalid scale %f, %f", __func__, c,
1321 active.startAmplitude, active.endAmplitude);
1322 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1323 }
1324 if (active.startAmplitude > CS40L26_PWLE_LEVEL_MAX) {
1325 active.startAmplitude = CS40L26_PWLE_LEVEL_MAX;
1326 ALOGD("%s: #%u: active: trim the start scale", __func__, c);
1327 }
1328 if (active.endAmplitude > CS40L26_PWLE_LEVEL_MAX) {
1329 active.endAmplitude = CS40L26_PWLE_LEVEL_MAX;
1330 ALOGD("%s: #%u: active: trim the end scale", __func__, c);
1331 }
1332
1333 if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
1334 active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
1335 active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
1336 active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
1337 mStatsApi->logError(kBadPrimitiveError);
1338 ALOGE("%s: #%u: active: Invalid frequency %f, %f", __func__, c,
1339 active.startFrequency, active.endFrequency);
1340 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1341 }
1342
1343 /* Append a new segment if current and previous amplitude and
1344 * frequency are not all the same.
1345 */
1346 if (!((active.startAmplitude == prevEndAmplitude) &&
1347 (active.startFrequency == prevEndFrequency))) {
1348 if (ch.constructActiveSegment(0, active.startAmplitude, active.startFrequency,
1349 false) < 0) {
1350 mStatsApi->logError(kPwleConstructionFailError);
1351 ALOGE("%s: #%u: active: Failed to construct for the start scale and "
1352 "frequency %f, %f",
1353 __func__, c, active.startAmplitude, active.startFrequency);
1354 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1355 }
1356 incrementIndex(&segmentIdx);
1357 }
1358
1359 if (active.startFrequency != active.endFrequency) {
1360 chirp = true;
1361 }
1362 if (ch.constructActiveSegment(active.duration, active.endAmplitude,
1363 active.endFrequency, chirp) < 0) {
1364 mStatsApi->logError(kPwleConstructionFailError);
1365 ALOGE("%s: #%u: active: Failed to construct for the end scale and frequency "
1366 "%f, %f",
1367 __func__, c, active.startAmplitude, active.startFrequency);
1368 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1369 }
1370 incrementIndex(&segmentIdx);
1371
1372 prevEndAmplitude = active.endAmplitude;
1373 prevEndFrequency = active.endFrequency;
1374 totalDuration += active.duration;
1375 chirp = false;
1376 break;
1377 }
1378 case PrimitivePwle::braking: {
1379 auto braking = e.get<PrimitivePwle::braking>();
1380 if (braking.braking > Braking::CLAB) {
1381 mStatsApi->logError(kBadPrimitiveError);
1382 ALOGE("%s: #%u: braking: Invalid braking type %d", __func__, c,
1383 braking.braking);
1384 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1385 } else if (!isClabSupported && (braking.braking == Braking::CLAB)) {
1386 mStatsApi->logError(kBadPrimitiveError);
1387 ALOGE("%s: #%u: braking: Unsupported CLAB braking", __func__, c);
1388 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1389 }
1390
1391 if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
1392 mStatsApi->logError(kBadPrimitiveError);
1393 ALOGE("%s: #%u: braking: Invalid duration %d", __func__, c, braking.duration);
1394 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1395 }
1396
1397 if (ch.constructBrakingSegment(0, braking.braking) < 0) {
1398 mStatsApi->logError(kPwleConstructionFailError);
1399 ALOGE("%s: #%u: braking: Failed to construct for type %d", __func__, c,
1400 braking.braking);
1401 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1402 }
1403 incrementIndex(&segmentIdx);
1404
1405 if (ch.constructBrakingSegment(braking.duration, braking.braking) < 0) {
1406 mStatsApi->logError(kPwleConstructionFailError);
1407 ALOGE("%s: #%u: braking: Failed to construct for type %d with duration %d",
1408 __func__, c, braking.braking, braking.duration);
1409 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1410 }
1411 incrementIndex(&segmentIdx);
1412
1413 resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
1414 totalDuration += braking.duration;
1415 break;
1416 }
1417 }
1418
1419 if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
1420 mStatsApi->logError(kPwleConstructionFailError);
1421 ALOGE("Too many PrimitivePwle section!");
1422 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1423 }
1424
1425 c++;
1426 }
1427 ch.flush();
1428
1429 /* Update wlength */
1430 totalDuration += MAX_COLD_START_LATENCY_MS;
1431 if (totalDuration > 0x7FFFF) {
1432 mStatsApi->logError(kPwleConstructionFailError);
1433 ALOGE("Total duration is too long (%d)!", totalDuration);
1434 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1435 } else {
1436 mFfEffects[WAVEFORM_PWLE].replay.length = totalDuration;
1437 }
1438
1439 if (ch.updateWLength(totalDuration) < 0) {
1440 mStatsApi->logError(kPwleConstructionFailError);
1441 ALOGE("%s: Failed to update the waveform length length", __func__);
1442 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1443 }
1444
1445 /* Update nsections */
1446 if (ch.updateNSection(segmentIdx) < 0) {
1447 mStatsApi->logError(kPwleConstructionFailError);
1448 ALOGE("%s: Failed to update the section count", __func__);
1449 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1450 }
1451
1452 return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch,
1453 callback);
1454 }
1455
isUnderExternalControl()1456 bool Vibrator::isUnderExternalControl() {
1457 HAPTICS_TRACE("isUnderExternalControl()");
1458 return mIsUnderExternalControl;
1459 }
1460
dump(int fd,const char ** args,uint32_t numArgs)1461 binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
1462 HAPTICS_TRACE("dump(fd:%d, args, numArgs:%u)", fd, numArgs);
1463 if (fd < 0) {
1464 ALOGE("Called debug() with invalid fd.");
1465 return STATUS_OK;
1466 }
1467
1468 (void)args;
1469 (void)numArgs;
1470
1471 dprintf(fd, "AIDL:\n");
1472
1473 dprintf(fd, " Global Gain: %0.2f\n", mLongEffectScale);
1474 dprintf(fd, " Active Effect ID: %" PRId32 "\n", mActiveId);
1475 dprintf(fd, " F0: %.02f\n", mResonantFrequency);
1476 dprintf(fd, " F0 Offset: %" PRIu32 "\n", mF0Offset);
1477 dprintf(fd, " Redc: %.02f\n", mRedc);
1478 dprintf(fd, " HAL State: %" PRIu32 "\n", halState);
1479
1480 dprintf(fd, " Voltage Levels:\n");
1481 dprintf(fd, " Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mTickEffectVol[0],
1482 mTickEffectVol[1]);
1483 dprintf(fd, " Click Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mClickEffectVol[0],
1484 mClickEffectVol[1]);
1485 dprintf(fd, " Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mLongEffectVol[0],
1486 mLongEffectVol[1]);
1487
1488 dprintf(fd, " FF Effect:\n");
1489 dprintf(fd, " Physical Waveform:\n");
1490 dprintf(fd, "\tId\tIndex\tt ->\tt'\n");
1491 for (uint8_t effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
1492 dprintf(fd, "\t%d\t%d\t%d\t%d\n", mFfEffects[effectId].id,
1493 mFfEffects[effectId].u.periodic.custom_data[1], mEffectDurations[effectId],
1494 mFfEffects[effectId].replay.length);
1495 }
1496 dprintf(fd, " OWT Waveform:\n");
1497 dprintf(fd, "\tId\tBytes\tData\n");
1498 for (uint8_t effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX;
1499 effectId++) {
1500 uint32_t numBytes = mFfEffects[effectId].u.periodic.custom_len * 2;
1501 std::stringstream ss;
1502 ss << " ";
1503 for (int i = 0; i < numBytes; i++) {
1504 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
1505 << (uint16_t)(*(
1506 reinterpret_cast<uint8_t *>(mFfEffects[effectId].u.periodic.custom_data) +
1507 i))
1508 << " ";
1509 }
1510 dprintf(fd, "\t%d\t%d\t{%s}\n", mFfEffects[effectId].id, numBytes, ss.str().c_str());
1511 }
1512
1513 dprintf(fd, "\n");
1514
1515 dprintf(fd, "Versions:\n");
1516 std::ifstream verFile;
1517 const auto verBinFileMode = std::ifstream::in | std::ifstream::binary;
1518 std::string ver;
1519 verFile.open("/sys/module/cs40l26_core/version");
1520 if (verFile.is_open()) {
1521 getline(verFile, ver);
1522 dprintf(fd, " Haptics Driver: %s\n", ver.c_str());
1523 verFile.close();
1524 }
1525 verFile.open("/sys/module/cl_dsp_core/version");
1526 if (verFile.is_open()) {
1527 getline(verFile, ver);
1528 dprintf(fd, " DSP Driver: %s\n", ver.c_str());
1529 verFile.close();
1530 }
1531 verFile.open("/vendor/firmware/cs40l26.wmfw", verBinFileMode);
1532 if (verFile.is_open()) {
1533 verFile.seekg(113);
1534 dprintf(fd, " cs40l26.wmfw: %d.%d.%d\n", verFile.get(), verFile.get(), verFile.get());
1535 verFile.close();
1536 }
1537 verFile.open("/vendor/firmware/cs40l26-calib.wmfw", verBinFileMode);
1538 if (verFile.is_open()) {
1539 verFile.seekg(113);
1540 dprintf(fd, " cs40l26-calib.wmfw: %d.%d.%d\n", verFile.get(), verFile.get(),
1541 verFile.get());
1542 verFile.close();
1543 }
1544 verFile.open("/vendor/firmware/cs40l26.bin", verBinFileMode);
1545 if (verFile.is_open()) {
1546 while (getline(verFile, ver)) {
1547 auto pos = ver.find("Date: ");
1548 if (pos != std::string::npos) {
1549 ver = ver.substr(pos + 6, pos + 15);
1550 dprintf(fd, " cs40l26.bin: %s\n", ver.c_str());
1551 break;
1552 }
1553 }
1554 verFile.close();
1555 }
1556 verFile.open("/vendor/firmware/cs40l26-svc.bin", verBinFileMode);
1557 if (verFile.is_open()) {
1558 verFile.seekg(36);
1559 getline(verFile, ver);
1560 ver = ver.substr(ver.rfind('\\') + 1);
1561 dprintf(fd, " cs40l26-svc.bin: %s\n", ver.c_str());
1562 verFile.close();
1563 }
1564 verFile.open("/vendor/firmware/cs40l26-calib.bin", verBinFileMode);
1565 if (verFile.is_open()) {
1566 verFile.seekg(36);
1567 getline(verFile, ver);
1568 ver = ver.substr(ver.rfind('\\') + 1);
1569 dprintf(fd, " cs40l26-calib.bin: %s\n", ver.c_str());
1570 verFile.close();
1571 }
1572
1573 dprintf(fd, "\n");
1574
1575 mHwApi->debug(fd);
1576
1577 dprintf(fd, "\n");
1578
1579 mHwCal->debug(fd);
1580
1581 dprintf(fd, "\n");
1582
1583 dprintf(fd, "Capo Info:\n");
1584 dprintf(fd, "Capo Enabled: %d\n", mContextEnable);
1585 if (mContextListener) {
1586 dprintf(fd, "Capo ID: 0x%x\n", (uint32_t)(mContextListener->getNanoppAppId()));
1587 dprintf(fd, "Capo State: %d\n", mContextListener->getCarriedPosition());
1588 }
1589
1590 dprintf(fd, "\n");
1591
1592 mStatsApi->debug(fd);
1593
1594 if (mHwApi->isDbcSupported()) {
1595 dprintf(fd, "\nDBC Enabled\n");
1596 }
1597
1598 fsync(fd);
1599 return STATUS_OK;
1600 }
1601
hasHapticAlsaDevice()1602 bool Vibrator::hasHapticAlsaDevice() {
1603 HAPTICS_TRACE("hasHapticAlsaDevice()");
1604 // We need to call findHapticAlsaDevice once only. Calling in the
1605 // constructor is too early in the boot process and the pcm file contents
1606 // are empty. Hence we make the call here once only right before we need to.
1607 if (!mConfigHapticAlsaDeviceDone) {
1608 if (mHwApi->getHapticAlsaDevice(&mCard, &mDevice)) {
1609 mHasHapticAlsaDevice = true;
1610 mConfigHapticAlsaDeviceDone = true;
1611 } else {
1612 mStatsApi->logError(kAlsaFailError);
1613 ALOGE("Haptic ALSA device not supported");
1614 }
1615 } else {
1616 ALOGD("Haptic ALSA device configuration done.");
1617 }
1618 return mHasHapticAlsaDevice;
1619 }
1620
getSimpleDetails(Effect effect,EffectStrength strength,uint32_t * outEffectIndex,uint32_t * outTimeMs,uint32_t * outVolLevel)1621 ndk::ScopedAStatus Vibrator::getSimpleDetails(Effect effect, EffectStrength strength,
1622 uint32_t *outEffectIndex, uint32_t *outTimeMs,
1623 uint32_t *outVolLevel) {
1624 HAPTICS_TRACE(
1625 "getSimpleDetails(effect:%s, strength:%s, outEffectIndex, outTimeMs"
1626 ", outVolLevel)",
1627 toString(effect).c_str(), toString(strength).c_str());
1628 uint32_t effectIndex;
1629 uint32_t timeMs;
1630 float intensity;
1631 uint32_t volLevel;
1632 switch (strength) {
1633 case EffectStrength::LIGHT:
1634 intensity = 0.5f;
1635 break;
1636 case EffectStrength::MEDIUM:
1637 intensity = 0.7f;
1638 break;
1639 case EffectStrength::STRONG:
1640 intensity = 1.0f;
1641 break;
1642 default:
1643 mStatsApi->logError(kUnsupportedOpError);
1644 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1645 }
1646
1647 switch (effect) {
1648 case Effect::TEXTURE_TICK:
1649 effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1650 intensity *= 0.5f;
1651 break;
1652 case Effect::TICK:
1653 effectIndex = WAVEFORM_CLICK_INDEX;
1654 intensity *= 0.5f;
1655 break;
1656 case Effect::CLICK:
1657 effectIndex = WAVEFORM_CLICK_INDEX;
1658 intensity *= 0.7f;
1659 break;
1660 case Effect::HEAVY_CLICK:
1661 effectIndex = WAVEFORM_CLICK_INDEX;
1662 intensity *= 1.0f;
1663 break;
1664 default:
1665 mStatsApi->logError(kUnsupportedOpError);
1666 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1667 }
1668
1669 volLevel = intensityToVolLevel(intensity, effectIndex);
1670 timeMs = mEffectDurations[effectIndex] + MAX_COLD_START_LATENCY_MS;
1671
1672 *outEffectIndex = effectIndex;
1673 *outTimeMs = timeMs;
1674 *outVolLevel = volLevel;
1675 return ndk::ScopedAStatus::ok();
1676 }
1677
getCompoundDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,DspMemChunk * outCh)1678 ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength strength,
1679 uint32_t *outTimeMs, DspMemChunk *outCh) {
1680 HAPTICS_TRACE("getCompoundDetails(effect:%s, strength:%s, outTimeMs, outCh)",
1681 toString(effect).c_str(), toString(strength).c_str());
1682 ndk::ScopedAStatus status;
1683 uint32_t timeMs = 0;
1684 uint32_t thisEffectIndex;
1685 uint32_t thisTimeMs;
1686 uint32_t thisVolLevel;
1687 switch (effect) {
1688 case Effect::DOUBLE_CLICK:
1689 status = getSimpleDetails(Effect::CLICK, strength, &thisEffectIndex, &thisTimeMs,
1690 &thisVolLevel);
1691 if (!status.isOk()) {
1692 mStatsApi->logError(kBadEffectError);
1693 return status;
1694 }
1695 timeMs += thisTimeMs;
1696 outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/,
1697 WAVEFORM_DOUBLE_CLICK_SILENCE_MS);
1698
1699 timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS;
1700
1701 status = getSimpleDetails(Effect::HEAVY_CLICK, strength, &thisEffectIndex, &thisTimeMs,
1702 &thisVolLevel);
1703 if (!status.isOk()) {
1704 mStatsApi->logError(kBadEffectError);
1705 return status;
1706 }
1707 timeMs += thisTimeMs;
1708
1709 outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/,
1710 0 /*delay*/);
1711 outCh->flush();
1712 if (outCh->updateNSection(2) < 0) {
1713 mStatsApi->logError(kComposeFailError);
1714 ALOGE("%s: Failed to update the section count", __func__);
1715 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1716 }
1717
1718 break;
1719 default:
1720 mStatsApi->logError(kUnsupportedOpError);
1721 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1722 }
1723
1724 *outTimeMs = timeMs;
1725 mFfEffects[WAVEFORM_COMPOSE].replay.length = static_cast<uint16_t>(timeMs);
1726
1727 return ndk::ScopedAStatus::ok();
1728 }
1729
getPrimitiveDetails(CompositePrimitive primitive,uint32_t * outEffectIndex)1730 ndk::ScopedAStatus Vibrator::getPrimitiveDetails(CompositePrimitive primitive,
1731 uint32_t *outEffectIndex) {
1732 HAPTICS_TRACE("getPrimitiveDetails(primitive:%s, outEffectIndex)", toString(primitive).c_str());
1733 uint32_t effectIndex;
1734 uint32_t primitiveBit = 1 << int32_t(primitive);
1735 if ((primitiveBit & mSupportedPrimitivesBits) == 0x0) {
1736 mStatsApi->logError(kUnsupportedOpError);
1737 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1738 }
1739
1740 switch (primitive) {
1741 case CompositePrimitive::NOOP:
1742 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1743 case CompositePrimitive::CLICK:
1744 effectIndex = WAVEFORM_CLICK_INDEX;
1745 break;
1746 case CompositePrimitive::THUD:
1747 effectIndex = WAVEFORM_THUD_INDEX;
1748 break;
1749 case CompositePrimitive::SPIN:
1750 effectIndex = WAVEFORM_SPIN_INDEX;
1751 break;
1752 case CompositePrimitive::QUICK_RISE:
1753 effectIndex = WAVEFORM_QUICK_RISE_INDEX;
1754 break;
1755 case CompositePrimitive::SLOW_RISE:
1756 effectIndex = WAVEFORM_SLOW_RISE_INDEX;
1757 break;
1758 case CompositePrimitive::QUICK_FALL:
1759 effectIndex = WAVEFORM_QUICK_FALL_INDEX;
1760 break;
1761 case CompositePrimitive::LIGHT_TICK:
1762 effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1763 break;
1764 case CompositePrimitive::LOW_TICK:
1765 effectIndex = WAVEFORM_LOW_TICK_INDEX;
1766 break;
1767 default:
1768 mStatsApi->logError(kUnsupportedOpError);
1769 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1770 }
1771
1772 *outEffectIndex = effectIndex;
1773
1774 return ndk::ScopedAStatus::ok();
1775 }
1776
performEffect(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * outTimeMs)1777 ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strength,
1778 const std::shared_ptr<IVibratorCallback> &callback,
1779 int32_t *outTimeMs) {
1780 HAPTICS_TRACE("performEffect(effect:%s, strength:%s, callback, outTimeMs)",
1781 toString(effect).c_str(), toString(strength).c_str());
1782 ndk::ScopedAStatus status;
1783 uint32_t effectIndex;
1784 uint32_t timeMs = 0;
1785 uint32_t volLevel;
1786 std::optional<DspMemChunk> maybeCh;
1787 switch (effect) {
1788 case Effect::TEXTURE_TICK:
1789 // fall-through
1790 case Effect::TICK:
1791 // fall-through
1792 case Effect::CLICK:
1793 // fall-through
1794 case Effect::HEAVY_CLICK:
1795 status = getSimpleDetails(effect, strength, &effectIndex, &timeMs, &volLevel);
1796 break;
1797 case Effect::DOUBLE_CLICK:
1798 maybeCh.emplace(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP);
1799 status = getCompoundDetails(effect, strength, &timeMs, &*maybeCh);
1800 volLevel = VOLTAGE_SCALE_MAX;
1801 break;
1802 default:
1803 mStatsApi->logError(kUnsupportedOpError);
1804 status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1805 break;
1806 }
1807 if (status.isOk()) {
1808 DspMemChunk *ch = maybeCh ? &*maybeCh : nullptr;
1809 status = performEffect(effectIndex, volLevel, ch, callback);
1810 }
1811
1812 *outTimeMs = timeMs;
1813 return status;
1814 }
1815
performEffect(uint32_t effectIndex,uint32_t volLevel,const DspMemChunk * ch,const std::shared_ptr<IVibratorCallback> & callback)1816 ndk::ScopedAStatus Vibrator::performEffect(uint32_t effectIndex, uint32_t volLevel,
1817 const DspMemChunk *ch,
1818 const std::shared_ptr<IVibratorCallback> &callback) {
1819 HAPTICS_TRACE("performEffect(effectIndex:%u, volLevel:%u, ch, callback)", effectIndex,
1820 volLevel);
1821 setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX, false);
1822
1823 return on(MAX_TIME_MS, effectIndex, ch, callback);
1824 }
1825
waitForComplete(std::shared_ptr<IVibratorCallback> && callback)1826 void Vibrator::waitForComplete(std::shared_ptr<IVibratorCallback> &&callback) {
1827 HAPTICS_TRACE("waitForComplete(callback)");
1828
1829 if (!mHwApi->pollVibeState(VIBE_STATE_HAPTIC, POLLING_TIMEOUT)) {
1830 ALOGW("Failed to get state \"Haptic\"");
1831 }
1832 halState = PLAYING;
1833 ATRACE_BEGIN("Vibrating");
1834 mHwApi->pollVibeState(VIBE_STATE_STOPPED);
1835 ATRACE_END();
1836 halState = STOPPED;
1837
1838 const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
1839 uint32_t effectCount = WAVEFORM_MAX_PHYSICAL_INDEX;
1840 if ((mActiveId >= WAVEFORM_MAX_PHYSICAL_INDEX) &&
1841 (!mHwApi->eraseOwtEffect(mActiveId, &mFfEffects))) {
1842 mStatsApi->logError(kHwApiError);
1843 ALOGE("Failed to clean up the composed effect %d", mActiveId);
1844 } else {
1845 ALOGD("waitForComplete: Vibrator is already off");
1846 }
1847 mHwApi->getEffectCount(&effectCount);
1848 // Do waveform number checking
1849 if ((effectCount > WAVEFORM_MAX_PHYSICAL_INDEX) &&
1850 (!mHwApi->eraseOwtEffect(WAVEFORM_MAX_INDEX, &mFfEffects))) {
1851 mStatsApi->logError(kHwApiError);
1852 ALOGE("Failed to forcibly clean up all composed effect");
1853 }
1854
1855 mActiveId = -1;
1856 halState = RESTORED;
1857
1858 if (callback) {
1859 auto ret = callback->onComplete();
1860 if (!ret.isOk()) {
1861 ALOGE("Failed completion callback: %d", ret.getExceptionCode());
1862 }
1863 }
1864 }
1865
intensityToVolLevel(float intensity,uint32_t effectIndex)1866 uint32_t Vibrator::intensityToVolLevel(float intensity, uint32_t effectIndex) {
1867 HAPTICS_TRACE("intensityToVolLevel(intensity:%f, effectIndex:%u)", intensity, effectIndex);
1868
1869 uint32_t volLevel;
1870 auto calc = [](float intst, std::array<uint32_t, 2> v) -> uint32_t {
1871 return std::lround(intst * (v[1] - v[0])) + v[0];
1872 };
1873
1874 switch (effectIndex) {
1875 case WAVEFORM_LIGHT_TICK_INDEX:
1876 volLevel = calc(intensity, mTickEffectVol);
1877 break;
1878 case WAVEFORM_QUICK_RISE_INDEX:
1879 // fall-through
1880 case WAVEFORM_QUICK_FALL_INDEX:
1881 volLevel = calc(intensity, mLongEffectVol);
1882 break;
1883 case WAVEFORM_CLICK_INDEX:
1884 // fall-through
1885 case WAVEFORM_THUD_INDEX:
1886 // fall-through
1887 case WAVEFORM_SPIN_INDEX:
1888 // fall-through
1889 case WAVEFORM_SLOW_RISE_INDEX:
1890 // fall-through
1891 default:
1892 volLevel = calc(intensity, mClickEffectVol);
1893 break;
1894 }
1895 return volLevel;
1896 }
1897
1898 } // namespace vibrator
1899 } // namespace hardware
1900 } // namespace android
1901 } // namespace aidl
1902