1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define ATRACE_TAG (ATRACE_TAG_VIBRATOR | ATRACE_TAG_HAL)
18 #define LOG_TAG "android.hardware.vibrator@1.3-service.coral"
19
20 #include "Vibrator.h"
21
22 #include <hardware/hardware.h>
23 #include <hardware/vibrator.h>
24 #include <log/log.h>
25 #include <utils/Trace.h>
26
27 #include <cinttypes>
28 #include <cmath>
29 #include <fstream>
30 #include <iostream>
31
32 #ifndef ARRAY_SIZE
33 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
34 #endif
35
36 namespace android {
37 namespace hardware {
38 namespace vibrator {
39 namespace V1_3 {
40 namespace implementation {
41
42 using Status = ::android::hardware::vibrator::V1_0::Status;
43 using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength;
44
45 static constexpr uint32_t BASE_CONTINUOUS_EFFECT_OFFSET = 32768;
46
47 static constexpr uint32_t WAVEFORM_SIMPLE_EFFECT_INDEX = 2;
48
49 static constexpr uint32_t WAVEFORM_TEXTURE_TICK_EFFECT_LEVEL = 0;
50
51 static constexpr uint32_t WAVEFORM_TICK_EFFECT_LEVEL = 1;
52
53 static constexpr uint32_t WAVEFORM_CLICK_EFFECT_LEVEL = 2;
54
55 static constexpr uint32_t WAVEFORM_HEAVY_CLICK_EFFECT_LEVEL = 3;
56
57 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_SILENCE_MS = 100;
58
59 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0;
60 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_THRESHOLD_MS = 50;
61 static constexpr uint32_t WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3 + BASE_CONTINUOUS_EFFECT_OFFSET;
62
63 static constexpr uint32_t WAVEFORM_TRIGGER_QUEUE_INDEX = 65534;
64
65 static constexpr uint32_t VOLTAGE_GLOBAL_SCALE_LEVEL = 5;
66 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
67
68 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby
69 static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1; // ALERT Irq Handling
70
71 static constexpr float AMP_ATTENUATE_STEP_SIZE = 0.125f;
72 static constexpr float EFFECT_FREQUENCY_KHZ = 48.0f;
73
amplitudeToScale(uint8_t amplitude,uint8_t maximum)74 static uint8_t amplitudeToScale(uint8_t amplitude, uint8_t maximum) {
75 return std::round((-20 * std::log10(amplitude / static_cast<float>(maximum))) /
76 (AMP_ATTENUATE_STEP_SIZE));
77 }
78
Vibrator(std::unique_ptr<HwApi> hwapi,std::unique_ptr<HwCal> hwcal)79 Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal)
80 : mHwApi(std::move(hwapi)), mHwCal(std::move(hwcal)) {
81 uint32_t caldata;
82 uint32_t effectDuration;
83
84 if (!mHwApi->setState(true)) {
85 ALOGE("Failed to set state (%d): %s", errno, strerror(errno));
86 }
87
88 if (mHwCal->getF0(&caldata)) {
89 mHwApi->setF0(caldata);
90 }
91 if (mHwCal->getRedc(&caldata)) {
92 mHwApi->setRedc(caldata);
93 }
94 if (mHwCal->getQ(&caldata)) {
95 mHwApi->setQ(caldata);
96 }
97 mHwCal->getVolLevels(&mVolLevels);
98
99 mHwApi->setEffectIndex(WAVEFORM_SIMPLE_EFFECT_INDEX);
100 mHwApi->getEffectDuration(&effectDuration);
101
102 mSimpleEffectDuration = std::ceil(effectDuration / EFFECT_FREQUENCY_KHZ);
103
104 const uint32_t scaleFall =
105 amplitudeToScale(mVolLevels[WAVEFORM_CLICK_EFFECT_LEVEL], VOLTAGE_SCALE_MAX);
106 const uint32_t scaleRise =
107 amplitudeToScale(mVolLevels[WAVEFORM_HEAVY_CLICK_EFFECT_LEVEL], VOLTAGE_SCALE_MAX);
108
109 mHwApi->setGpioFallIndex(WAVEFORM_SIMPLE_EFFECT_INDEX);
110 mHwApi->setGpioFallScale(scaleFall);
111 mHwApi->setGpioRiseIndex(WAVEFORM_SIMPLE_EFFECT_INDEX);
112 mHwApi->setGpioRiseScale(scaleRise);
113 }
114
on(uint32_t timeoutMs,uint32_t effectIndex)115 Return<Status> Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex) {
116 mHwApi->setEffectIndex(effectIndex);
117 mHwApi->setDuration(timeoutMs);
118 mHwApi->setActivate(1);
119
120 return Status::OK;
121 }
122
123 // Methods from ::android::hardware::vibrator::V1_1::IVibrator follow.
on(uint32_t timeoutMs)124 Return<Status> Vibrator::on(uint32_t timeoutMs) {
125 ATRACE_NAME("Vibrator::on");
126 const uint32_t index = timeoutMs < WAVEFORM_LONG_VIBRATION_THRESHOLD_MS
127 ? WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX
128 : WAVEFORM_LONG_VIBRATION_EFFECT_INDEX;
129 if (MAX_COLD_START_LATENCY_MS <= UINT32_MAX - timeoutMs) {
130 timeoutMs += MAX_COLD_START_LATENCY_MS;
131 }
132 setGlobalAmplitude(true);
133 return on(timeoutMs, index);
134 }
135
off()136 Return<Status> Vibrator::off() {
137 ATRACE_NAME("Vibrator::off");
138 setGlobalAmplitude(false);
139 if (!mHwApi->setActivate(0)) {
140 ALOGE("Failed to turn vibrator off (%d): %s", errno, strerror(errno));
141 return Status::UNKNOWN_ERROR;
142 }
143 return Status::OK;
144 }
145
supportsAmplitudeControl()146 Return<bool> Vibrator::supportsAmplitudeControl() {
147 ATRACE_NAME("Vibrator::supportsAmplitudeControl");
148 return !isUnderExternalControl() && mHwApi->hasEffectScale();
149 }
150
setAmplitude(uint8_t amplitude)151 Return<Status> Vibrator::setAmplitude(uint8_t amplitude) {
152 ATRACE_NAME("Vibrator::setAmplitude");
153 if (!amplitude) {
154 return Status::BAD_VALUE;
155 }
156
157 if (!isUnderExternalControl()) {
158 return setEffectAmplitude(amplitude, UINT8_MAX);
159 } else {
160 return Status::UNSUPPORTED_OPERATION;
161 }
162 }
163
setEffectAmplitude(uint8_t amplitude,uint8_t maximum)164 Return<Status> Vibrator::setEffectAmplitude(uint8_t amplitude, uint8_t maximum) {
165 int32_t scale = amplitudeToScale(amplitude, maximum);
166
167 if (!mHwApi->setEffectScale(scale)) {
168 ALOGE("Failed to set effect amplitude (%d): %s", errno, strerror(errno));
169 return Status::UNKNOWN_ERROR;
170 }
171
172 return Status::OK;
173 }
174
setGlobalAmplitude(bool set)175 Return<Status> Vibrator::setGlobalAmplitude(bool set) {
176 uint8_t amplitude = set ? mVolLevels[VOLTAGE_GLOBAL_SCALE_LEVEL] : VOLTAGE_SCALE_MAX;
177 int32_t scale = amplitudeToScale(amplitude, VOLTAGE_SCALE_MAX);
178
179 if (!mHwApi->setGlobalScale(scale)) {
180 ALOGE("Failed to set global amplitude (%d): %s", errno, strerror(errno));
181 return Status::UNKNOWN_ERROR;
182 }
183
184 return Status::OK;
185 }
186
187 // Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
188
supportsExternalControl()189 Return<bool> Vibrator::supportsExternalControl() {
190 ATRACE_NAME("Vibrator::supportsExternalControl");
191 return (mHwApi->hasAspEnable() ? true : false);
192 }
193
setExternalControl(bool enabled)194 Return<Status> Vibrator::setExternalControl(bool enabled) {
195 ATRACE_NAME("Vibrator::setExternalControl");
196 setGlobalAmplitude(enabled);
197
198 if (!mHwApi->setAspEnable(enabled)) {
199 ALOGE("Failed to set external control (%d): %s", errno, strerror(errno));
200 return Status::UNKNOWN_ERROR;
201 }
202 return Status::OK;
203 }
204
isUnderExternalControl()205 bool Vibrator::isUnderExternalControl() {
206 bool isAspEnabled;
207 mHwApi->getAspEnable(&isAspEnabled);
208 return isAspEnabled;
209 }
210
211 // Methods from ::android.hidl.base::V1_0::IBase follow.
212
debug(const hidl_handle & handle,const hidl_vec<hidl_string> &)213 Return<void> Vibrator::debug(const hidl_handle &handle,
214 const hidl_vec<hidl_string> & /* options */) {
215 if (handle == nullptr || handle->numFds < 1 || handle->data[0] < 0) {
216 ALOGE("Called debug() with invalid fd.");
217 return Void();
218 }
219
220 int fd = handle->data[0];
221
222 dprintf(fd, "HIDL:\n");
223
224 dprintf(fd, " Voltage Levels:");
225 for (auto v : mVolLevels) {
226 dprintf(fd, " %" PRIu32, v);
227 }
228 dprintf(fd, "\n");
229
230 dprintf(fd, " Effect Duration: %" PRIu32 "\n", mSimpleEffectDuration);
231
232 dprintf(fd, "\n");
233
234 mHwApi->debug(fd);
235
236 dprintf(fd, "\n");
237
238 mHwCal->debug(fd);
239
240 fsync(fd);
241 return Void();
242 }
243
244 template <typename T>
performWrapper(T effect,EffectStrength strength,perform_cb _hidl_cb)245 Return<void> Vibrator::performWrapper(T effect, EffectStrength strength, perform_cb _hidl_cb) {
246 ATRACE_NAME("Vibrator::performWrapper");
247 auto validRange = hidl_enum_range<T>();
248 if (effect < *validRange.begin() || effect > *std::prev(validRange.end())) {
249 _hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
250 return Void();
251 }
252 return performEffect(static_cast<Effect>(effect), strength, _hidl_cb);
253 }
254
perform(V1_0::Effect effect,EffectStrength strength,perform_cb _hidl_cb)255 Return<void> Vibrator::perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
256 return performWrapper(effect, strength, _hidl_cb);
257 }
258
perform_1_1(V1_1::Effect_1_1 effect,EffectStrength strength,perform_cb _hidl_cb)259 Return<void> Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength,
260 perform_cb _hidl_cb) {
261 return performWrapper(effect, strength, _hidl_cb);
262 }
263
perform_1_2(V1_2::Effect effect,EffectStrength strength,perform_cb _hidl_cb)264 Return<void> Vibrator::perform_1_2(V1_2::Effect effect, EffectStrength strength,
265 perform_cb _hidl_cb) {
266 return performWrapper(effect, strength, _hidl_cb);
267 }
268
perform_1_3(Effect effect,EffectStrength strength,perform_cb _hidl_cb)269 Return<void> Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
270 return performWrapper(effect, strength, _hidl_cb);
271 }
272
getSimpleDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,uint32_t * outVolLevel)273 Return<Status> Vibrator::getSimpleDetails(Effect effect, EffectStrength strength,
274 uint32_t *outTimeMs, uint32_t *outVolLevel) {
275 uint32_t timeMs;
276 uint32_t volLevel;
277 uint32_t volIndex;
278 int8_t volOffset;
279
280 switch (strength) {
281 case EffectStrength::LIGHT:
282 volOffset = -1;
283 break;
284 case EffectStrength::MEDIUM:
285 volOffset = 0;
286 break;
287 case EffectStrength::STRONG:
288 volOffset = 1;
289 break;
290 default:
291 return Status::UNSUPPORTED_OPERATION;
292 }
293
294 switch (effect) {
295 case Effect::TEXTURE_TICK:
296 volIndex = WAVEFORM_TEXTURE_TICK_EFFECT_LEVEL;
297 volOffset = 0;
298 break;
299 case Effect::TICK:
300 volIndex = WAVEFORM_TICK_EFFECT_LEVEL;
301 volOffset = 0;
302 break;
303 case Effect::CLICK:
304 volIndex = WAVEFORM_CLICK_EFFECT_LEVEL;
305 break;
306 case Effect::HEAVY_CLICK:
307 volIndex = WAVEFORM_HEAVY_CLICK_EFFECT_LEVEL;
308 break;
309 default:
310 return Status::UNSUPPORTED_OPERATION;
311 }
312
313 volLevel = mVolLevels[volIndex + volOffset];
314 timeMs = mSimpleEffectDuration + MAX_COLD_START_LATENCY_MS;
315
316 *outTimeMs = timeMs;
317 *outVolLevel = volLevel;
318
319 return Status::OK;
320 }
321
getCompoundDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,uint32_t *,std::string * outEffectQueue)322 Return<Status> Vibrator::getCompoundDetails(Effect effect, EffectStrength strength,
323 uint32_t *outTimeMs, uint32_t * /*outVolLevel*/,
324 std::string *outEffectQueue) {
325 Status status;
326 uint32_t timeMs;
327 std::ostringstream effectBuilder;
328 uint32_t thisTimeMs;
329 uint32_t thisVolLevel;
330
331 switch (effect) {
332 case Effect::DOUBLE_CLICK:
333 timeMs = 0;
334
335 status = getSimpleDetails(Effect::CLICK, strength, &thisTimeMs, &thisVolLevel);
336 if (status != Status::OK) {
337 return status;
338 }
339 effectBuilder << WAVEFORM_SIMPLE_EFFECT_INDEX << "." << thisVolLevel;
340 timeMs += thisTimeMs;
341
342 effectBuilder << ",";
343
344 effectBuilder << WAVEFORM_DOUBLE_CLICK_SILENCE_MS;
345 timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS;
346
347 effectBuilder << ",";
348
349 status = getSimpleDetails(Effect::HEAVY_CLICK, strength, &thisTimeMs, &thisVolLevel);
350 if (status != Status::OK) {
351 return status;
352 }
353 effectBuilder << WAVEFORM_SIMPLE_EFFECT_INDEX << "." << thisVolLevel;
354 timeMs += thisTimeMs;
355
356 break;
357 default:
358 return Status::UNSUPPORTED_OPERATION;
359 }
360
361 *outTimeMs = timeMs;
362 *outEffectQueue = effectBuilder.str();
363
364 return Status::OK;
365 }
366
setEffectQueue(const std::string & effectQueue)367 Return<Status> Vibrator::setEffectQueue(const std::string &effectQueue) {
368 if (!mHwApi->setEffectQueue(effectQueue)) {
369 ALOGE("Failed to write \"%s\" to effect queue (%d): %s", effectQueue.c_str(), errno,
370 strerror(errno));
371 return Status::UNKNOWN_ERROR;
372 }
373
374 return Status::OK;
375 }
376
performEffect(Effect effect,EffectStrength strength,perform_cb _hidl_cb)377 Return<void> Vibrator::performEffect(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
378 Status status = Status::OK;
379 uint32_t timeMs = 0;
380 uint32_t effectIndex;
381 uint32_t volLevel;
382 std::string effectQueue;
383
384 switch (effect) {
385 case Effect::TEXTURE_TICK:
386 // fall-through
387 case Effect::TICK:
388 // fall-through
389 case Effect::CLICK:
390 // fall-through
391 case Effect::HEAVY_CLICK:
392 status = getSimpleDetails(effect, strength, &timeMs, &volLevel);
393 break;
394 case Effect::DOUBLE_CLICK:
395 status = getCompoundDetails(effect, strength, &timeMs, &volLevel, &effectQueue);
396 break;
397 default:
398 status = Status::UNSUPPORTED_OPERATION;
399 break;
400 }
401 if (status != Status::OK) {
402 goto exit;
403 }
404
405 if (!effectQueue.empty()) {
406 status = setEffectQueue(effectQueue);
407 if (status != Status::OK) {
408 goto exit;
409 }
410 setEffectAmplitude(VOLTAGE_SCALE_MAX, VOLTAGE_SCALE_MAX);
411 effectIndex = WAVEFORM_TRIGGER_QUEUE_INDEX;
412 } else {
413 setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX);
414 effectIndex = WAVEFORM_SIMPLE_EFFECT_INDEX;
415 }
416
417 on(timeMs, effectIndex);
418
419 exit:
420
421 _hidl_cb(status, timeMs);
422
423 return Void();
424 }
425
426 } // namespace implementation
427 } // namespace V1_3
428 } // namespace vibrator
429 } // namespace hardware
430 } // namespace android
431