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