• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "Vibrator.h"
18 #include "utils.h"
19 
20 #include <android/looper.h>
21 #include <android/sensor.h>
22 #include <cutils/properties.h>
23 #include <hardware/hardware.h>
24 #include <hardware/vibrator.h>
25 #include <log/log.h>
26 #include <utils/Errors.h>
27 #include <utils/Trace.h>
28 
29 #include <cinttypes>
30 #include <cmath>
31 #include <fstream>
32 #include <iostream>
33 #include <numeric>
34 
35 namespace aidl {
36 namespace android {
37 namespace hardware {
38 namespace vibrator {
39 
40 using ::android::NO_ERROR;
41 using ::android::UNEXPECTED_NULL;
42 using ::android::NO_INIT;
43 
44 static constexpr int8_t MAX_RTP_INPUT = 127;
45 static constexpr int8_t MIN_RTP_INPUT = 0;
46 
47 static constexpr char RTP_MODE[] = "rtp";
48 static constexpr char WAVEFORM_MODE[] = "waveform";
49 
50 // Use effect #1 in the waveform library for CLICK effect
51 static constexpr char WAVEFORM_CLICK_EFFECT_SEQ[] = "1 0";
52 
53 // Use effect #2 in the waveform library for TICK effect
54 static constexpr char WAVEFORM_TICK_EFFECT_SEQ[] = "2 0";
55 
56 // Use effect #3 in the waveform library for DOUBLE_CLICK effect
57 static constexpr char WAVEFORM_DOUBLE_CLICK_EFFECT_SEQ[] = "3 0";
58 
59 // Use effect #4 in the waveform library for HEAVY_CLICK effect
60 static constexpr char WAVEFORM_HEAVY_CLICK_EFFECT_SEQ[] = "4 0";
61 
62 // UT team design those target G values
63 static constexpr std::array<float, 5> EFFECT_TARGET_G = {0.115, 0.160, 0.190, 0.310, 0.45};
64 static constexpr std::array<float, 3> STEADY_TARGET_G = {0.95, 0.90, 0.50};
65 
66 struct SensorContext {
67     ASensorEventQueue *queue;
68 };
69 static std::vector<float> sXAxleData;
70 static std::vector<float> sYAxleData;
71 static uint64_t sEndTime = 0;
72 static struct timespec sGetTime;
73 
74 #define MAX_VOLTAGE 3.2
75 #define FLOAT_EPS 1e-7
76 #define SENSOR_DATA_NUM 20
77 // Set GSensor polling time as 3ms
78 #define GSENSOR_POLLING_TIME 3
79 // Set sensing period to 2s
80 #define SENSING_PERIOD 2000000000
81 #define VIBRATION_MOTION_TIME_THRESHOLD 100
82 #define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
83 #define ENABLE_MOTION_AWARENESS(x) ((x) > (VIBRATION_MOTION_TIME_THRESHOLD)? (true):(false))
84 
GSensorCallback(int fd,int events,void * data)85 int GSensorCallback(__attribute__((unused)) int fd, __attribute__((unused)) int events,
86                     void *data) {
87     ASensorEvent event;
88     int event_count = 0;
89     SensorContext *context = reinterpret_cast<SensorContext *>(data);
90     event_count = ASensorEventQueue_getEvents(context->queue, &event, 1);
91     sXAxleData.push_back(event.data[0]);
92     sYAxleData.push_back(event.data[1]);
93     return 1;
94 }
95 // TODO: b/152305970
PollGSensor()96 int32_t PollGSensor() {
97     int err = NO_ERROR, counter = 0;
98     ASensorManager *sensorManager = nullptr;
99     ASensorRef GSensor;
100     ALooper *looper;
101     struct SensorContext context = {nullptr};
102 
103     // Get proximity sensor events from the NDK
104     sensorManager = ASensorManager_getInstanceForPackage("");
105     if (!sensorManager) {
106         ALOGE("%s: Sensor manager is NULL.\n", __func__);
107         return UNEXPECTED_NULL;
108     }
109     GSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_GRAVITY);
110     if (GSensor == nullptr) {
111         ALOGE("%s: Unable to get g sensor\n", __func__);
112         return UNEXPECTED_NULL;
113     }
114 
115     looper = ALooper_forThread();
116     if (looper == nullptr) {
117         looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
118     }
119 
120     context.queue =
121         ASensorManager_createEventQueue(sensorManager, looper, 0, GSensorCallback, &context);
122 
123     err = ASensorEventQueue_registerSensor(context.queue, GSensor, 0, 0);
124     if (err < 0) {
125         ALOGE("%s:Unable to register for G sensor events\n", __func__);
126         return NO_INIT;
127     } else {
128         for (counter = 0; counter < SENSOR_DATA_NUM; counter++) {
129             ALooper_pollOnce(GSENSOR_POLLING_TIME, nullptr, nullptr, nullptr);
130         }
131     }
132 
133     if (sensorManager != nullptr && context.queue != nullptr) {
134         ASensorEventQueue_disableSensor(context.queue, GSensor);
135         ASensorManager_destroyEventQueue(sensorManager, context.queue);
136     }
137 
138     return NO_ERROR;
139 }
140 
141 // Temperature protection upper bound 10°C and lower bound 5°C
142 static constexpr int32_t TEMP_UPPER_BOUND = 10000;
143 static constexpr int32_t TEMP_LOWER_BOUND = 5000;
144 // Steady vibration's voltage in lower bound guarantee
145 static uint32_t STEADY_VOLTAGE_LOWER_BOUND = 90;  // 1.8 Vpeak
146 
freqPeriodFormula(std::uint32_t in)147 static std::uint32_t freqPeriodFormula(std::uint32_t in) {
148     return 1000000000 / (24615 * in);
149 }
150 
convertLevelsToOdClamp(float voltageLevel,uint32_t lraPeriod)151 static std::uint32_t convertLevelsToOdClamp(float voltageLevel, uint32_t lraPeriod) {
152     float odClamp;
153 
154     odClamp = voltageLevel /
155               ((21.32 / 1000.0) *
156                sqrt(1.0 - (static_cast<float>(freqPeriodFormula(lraPeriod)) * 8.0 / 10000.0)));
157 
158     return round(odClamp);
159 }
160 
targetGToVlevelsUnderLinearEquation(std::array<float,4> inputCoeffs,float targetG)161 static float targetGToVlevelsUnderLinearEquation(std::array<float, 4> inputCoeffs, float targetG) {
162     // Implement linear equation to get voltage levels, f(x) = ax + b
163     // 0 to 3.2 is our valid output
164     float outPutVal = 0.0f;
165     outPutVal = (targetG - inputCoeffs[1]) / inputCoeffs[0];
166     if ((outPutVal > FLOAT_EPS) && (outPutVal <= MAX_VOLTAGE)) {
167         return outPutVal;
168     } else {
169         return 0.0f;
170     }
171 }
172 
targetGToVlevelsUnderCubicEquation(std::array<float,4> inputCoeffs,float targetG)173 static float targetGToVlevelsUnderCubicEquation(std::array<float, 4> inputCoeffs, float targetG) {
174     // Implement cubic equation to get voltage levels, f(x) = ax^3 + bx^2 + cx + d
175     // 0 to 3.2 is our valid output
176     float AA = 0.0f, BB = 0.0f, CC = 0.0f, Delta = 0.0f;
177     float Y1 = 0.0f, Y2 = 0.0f, K = 0.0f, T = 0.0f, sita = 0.0f;
178     float outPutVal = 0.0f;
179     float oneHalf = 1.0 / 2.0, oneThird = 1.0 / 3.0;
180     float cosSita = 0.0f, sinSitaSqrt3 = 0.0f, sqrtA = 0.0f;
181 
182     AA = inputCoeffs[1] * inputCoeffs[1] - 3.0 * inputCoeffs[0] * inputCoeffs[2];
183     BB = inputCoeffs[1] * inputCoeffs[2] - 9.0 * inputCoeffs[0] * (inputCoeffs[3] - targetG);
184     CC = inputCoeffs[2] * inputCoeffs[2] - 3.0 * inputCoeffs[1] * (inputCoeffs[3] - targetG);
185 
186     Delta = BB * BB - 4.0 * AA * CC;
187 
188     // There are four discriminants in Shengjin formula.
189     // https://zh.wikipedia.org/wiki/%E4%B8%89%E6%AC%A1%E6%96%B9%E7%A8%8B#%E7%9B%9B%E9%87%91%E5%85%AC%E5%BC%8F%E6%B3%95
190     if ((fabs(AA) <= FLOAT_EPS) && (fabs(BB) <= FLOAT_EPS)) {
191         // Case 1: A = B = 0
192         outPutVal = -inputCoeffs[1] / (3 * inputCoeffs[0]);
193         if ((outPutVal > FLOAT_EPS) && (outPutVal <= MAX_VOLTAGE)) {
194             return outPutVal;
195         }
196         return 0.0f;
197     } else if (Delta > FLOAT_EPS) {
198         // Case 2: Delta > 0
199         Y1 = AA * inputCoeffs[1] + 3.0 * inputCoeffs[0] * (-BB + pow(Delta, oneHalf)) / 2.0;
200         Y2 = AA * inputCoeffs[1] + 3.0 * inputCoeffs[0] * (-BB - pow(Delta, oneHalf)) / 2.0;
201 
202         if ((Y1 < -FLOAT_EPS) && (Y2 > FLOAT_EPS)) {
203             return (-inputCoeffs[1] + pow(-Y1, oneThird) - pow(Y2, oneThird)) /
204                    (3.0 * inputCoeffs[0]);
205         } else if ((Y1 > FLOAT_EPS) && (Y2 < -FLOAT_EPS)) {
206             return (-inputCoeffs[1] - pow(Y1, oneThird) + pow(-Y2, oneThird)) /
207                    (3.0 * inputCoeffs[0]);
208         } else if ((Y1 < -FLOAT_EPS) && (Y2 < -FLOAT_EPS)) {
209             return (-inputCoeffs[1] + pow(-Y1, oneThird) + pow(-Y2, oneThird)) /
210                    (3.0 * inputCoeffs[0]);
211         } else {
212             return (-inputCoeffs[1] - pow(Y1, oneThird) - pow(Y2, oneThird)) /
213                    (3.0 * inputCoeffs[0]);
214         }
215         return 0.0f;
216     } else if (Delta < -FLOAT_EPS) {
217         // Case 3: Delta < 0
218         T = (2 * AA * inputCoeffs[1] - 3 * inputCoeffs[0] * BB) / (2 * AA * sqrt(AA));
219         sita = acos(T);
220         cosSita = cos(sita / 3);
221         sinSitaSqrt3 = sqrt(3.0) * sin(sita / 3);
222         sqrtA = sqrt(AA);
223 
224         outPutVal = (-inputCoeffs[1] - 2 * sqrtA * cosSita) / (3 * inputCoeffs[0]);
225         if ((outPutVal > FLOAT_EPS) && (outPutVal <= MAX_VOLTAGE)) {
226             return outPutVal;
227         }
228         outPutVal = (-inputCoeffs[1] + sqrtA * (cosSita + sinSitaSqrt3)) / (3 * inputCoeffs[0]);
229         if ((outPutVal > FLOAT_EPS) && (outPutVal <= MAX_VOLTAGE)) {
230             return outPutVal;
231         }
232         outPutVal = (-inputCoeffs[1] + sqrtA * (cosSita - sinSitaSqrt3)) / (3 * inputCoeffs[0]);
233         if ((outPutVal > FLOAT_EPS) && (outPutVal <= MAX_VOLTAGE)) {
234             return outPutVal;
235         }
236         return 0.0f;
237     } else if (Delta <= FLOAT_EPS) {
238         // Case 4: Delta = 0
239         K = BB / AA;
240         outPutVal = (-inputCoeffs[1] / inputCoeffs[0] + K);
241         if ((outPutVal > FLOAT_EPS) && (outPutVal <= MAX_VOLTAGE)) {
242             return outPutVal;
243         }
244         outPutVal = (-K / 2);
245         if ((outPutVal > FLOAT_EPS) && (outPutVal <= MAX_VOLTAGE)) {
246             return outPutVal;
247         }
248         return 0.0f;
249     } else {
250         // Exception handling
251         return 0.0f;
252     }
253 }
254 
vLevelsToTargetGUnderCubicEquation(std::array<float,4> inputCoeffs,float vLevel)255 static float vLevelsToTargetGUnderCubicEquation(std::array<float, 4> inputCoeffs, float vLevel) {
256     float inputVoltage = 0.0f;
257     inputVoltage = vLevel * MAX_VOLTAGE;
258     return inputCoeffs[0] * pow(inputVoltage, 3) + inputCoeffs[1] * pow(inputVoltage, 2) +
259            inputCoeffs[2] * inputVoltage + inputCoeffs[3];
260 }
261 
motionAwareness()262 static bool motionAwareness() {
263     float avgX = 0.0, avgY = 0.0;
264     uint64_t current_time = 0;
265     clock_gettime(CLOCK_MONOTONIC, &sGetTime);
266     current_time = ((uint64_t)sGetTime.tv_sec * 1000 * 1000 * 1000) + sGetTime.tv_nsec;
267 
268     if ((current_time - sEndTime) > SENSING_PERIOD) {
269         sXAxleData.clear();
270         sYAxleData.clear();
271         PollGSensor();
272         clock_gettime(CLOCK_MONOTONIC, &sGetTime);
273         sEndTime = ((uint64_t)sGetTime.tv_sec * 1000 * 1000 * 1000) + sGetTime.tv_nsec;
274     }
275 
276     avgX = std::accumulate(sXAxleData.begin(), sXAxleData.end(), 0.0) / sXAxleData.size();
277     avgY = std::accumulate(sYAxleData.begin(), sYAxleData.end(), 0.0) / sYAxleData.size();
278 
279     if ((avgX > -1.3) && (avgX < 1.3) && (avgY > -0.8) && (avgY < 0.8)) {
280         return false;
281     } else {
282         return true;
283     }
284 }
285 
286 using utils::toUnderlying;
287 
Vibrator(std::unique_ptr<HwApi> hwapi,std::unique_ptr<HwCal> hwcal)288 Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal)
289     : mHwApi(std::move(hwapi)), mHwCal(std::move(hwcal)) {
290     std::string autocal;
291     uint32_t lraPeriod = 0, lpTrigSupport = 0;
292     bool hasEffectCoeffs = false, hasSteadyCoeffs = false;
293     std::array<float, 4> effectCoeffs = {0};
294     std::array<float, 4> steadyCoeffs = {0};
295 
296     if (!mHwApi->setState(true)) {
297         ALOGE("Failed to set state (%d): %s", errno, strerror(errno));
298     }
299 
300     if (mHwCal->getAutocal(&autocal)) {
301         mHwApi->setAutocal(autocal);
302     }
303     mHwCal->getLraPeriod(&lraPeriod);
304 
305     mHwCal->getCloseLoopThreshold(&mCloseLoopThreshold);
306     mHwCal->getDynamicConfig(&mDynamicConfig);
307 
308     if (mDynamicConfig) {
309         uint8_t i = 0;
310         float tempVolLevel = 0.0f;
311         float tempAmpMax = 0.0f;
312         uint32_t longFreqencyShift = 0;
313         uint32_t shortVoltageMax = 0, longVoltageMax = 0;
314         uint32_t shape = 0;
315 
316         mHwCal->getLongFrequencyShift(&longFreqencyShift);
317         mHwCal->getShortVoltageMax(&shortVoltageMax);
318         mHwCal->getLongVoltageMax(&longVoltageMax);
319 
320         hasEffectCoeffs = mHwCal->getEffectCoeffs(&effectCoeffs);
321         for (i = 0; i < 5; i++) {
322             if (hasEffectCoeffs) {
323                 // Use linear approach to get the target voltage levels
324                 if ((effectCoeffs[2] == 0) && (effectCoeffs[3] == 0)) {
325                     tempVolLevel =
326                         targetGToVlevelsUnderLinearEquation(effectCoeffs, EFFECT_TARGET_G[i]);
327                     mEffectTargetOdClamp[i] = convertLevelsToOdClamp(tempVolLevel, lraPeriod);
328                 } else {
329                     // Use cubic approach to get the target voltage levels
330                     tempVolLevel =
331                         targetGToVlevelsUnderCubicEquation(effectCoeffs, EFFECT_TARGET_G[i]);
332                     mEffectTargetOdClamp[i] = convertLevelsToOdClamp(tempVolLevel, lraPeriod);
333                 }
334             } else {
335                 mEffectTargetOdClamp[i] = shortVoltageMax;
336             }
337         }
338         // Add a boundary protection for level 5 only, since
339         // some devices might not be able to reach the maximum target G
340         if ((mEffectTargetOdClamp[4] <= 0) || (mEffectTargetOdClamp[4] > shortVoltageMax)) {
341             mEffectTargetOdClamp[4] = shortVoltageMax;
342         }
343 
344         mHwCal->getEffectShape(&shape);
345         mEffectConfig.reset(new VibrationConfig({
346             .shape = (shape == UINT32_MAX) ? WaveShape::SINE : static_cast<WaveShape>(shape),
347             .odClamp = &mEffectTargetOdClamp[0],
348             .olLraPeriod = lraPeriod,
349         }));
350 
351         hasSteadyCoeffs = mHwCal->getSteadyCoeffs(&steadyCoeffs);
352         if (hasSteadyCoeffs) {
353             for (i = 0; i < 3; i++) {
354                 // Use cubic approach to get the steady target voltage levels
355                 // For steady level 3 voltage which is used for non-motion voltage, we use
356                 // interpolation method to calculate the voltage via 20% of MAX
357                 // voltage, 60% of MAX voltage and steady level 3 target G
358                 if (i == 2) {
359                     tempVolLevel = ((STEADY_TARGET_G[2] -
360                                      vLevelsToTargetGUnderCubicEquation(steadyCoeffs, 0.2)) *
361                                     0.4 * MAX_VOLTAGE) /
362                                        (vLevelsToTargetGUnderCubicEquation(steadyCoeffs, 0.6) -
363                                         vLevelsToTargetGUnderCubicEquation(steadyCoeffs, 0.2)) +
364                                    0.2 * MAX_VOLTAGE;
365                 } else {
366                     tempVolLevel =
367                         targetGToVlevelsUnderCubicEquation(steadyCoeffs, STEADY_TARGET_G[i]);
368                 }
369                 mSteadyTargetOdClamp[i] = convertLevelsToOdClamp(tempVolLevel, lraPeriod);
370                 if ((mSteadyTargetOdClamp[i] <= 0) || (mSteadyTargetOdClamp[i] > longVoltageMax)) {
371                     mSteadyTargetOdClamp[i] = longVoltageMax;
372                 }
373             }
374         } else {
375             mSteadyTargetOdClamp[0] =
376                 mHwCal->getSteadyAmpMax(&tempAmpMax)
377                     ? round((STEADY_TARGET_G[0] / tempAmpMax) * longVoltageMax)
378                     : longVoltageMax;
379             mSteadyTargetOdClamp[2] =
380                 mHwCal->getSteadyAmpMax(&tempAmpMax)
381                     ? round((STEADY_TARGET_G[2] / tempAmpMax) * longVoltageMax)
382                     : longVoltageMax;
383         }
384         mHwCal->getSteadyShape(&shape);
385         mSteadyConfig.reset(new VibrationConfig({
386             .shape = (shape == UINT32_MAX) ? WaveShape::SQUARE : static_cast<WaveShape>(shape),
387             .odClamp = &mSteadyTargetOdClamp[0],
388             .olLraPeriod = lraPeriod,
389         }));
390         mSteadyOlLraPeriod = lraPeriod;
391         // 1. Change long lra period to frequency
392         // 2. Get frequency': subtract the frequency shift from the frequency
393         // 3. Get final long lra period after put the frequency' to formula
394         mSteadyOlLraPeriodShift =
395             freqPeriodFormula(freqPeriodFormula(lraPeriod) - longFreqencyShift);
396     }
397 
398     mHwApi->setOlLraPeriod(lraPeriod);
399 
400     mHwCal->getClickDuration(&mClickDuration);
401     mHwCal->getTickDuration(&mTickDuration);
402     mHwCal->getDoubleClickDuration(&mDoubleClickDuration);
403     mHwCal->getHeavyClickDuration(&mHeavyClickDuration);
404 
405     // This enables effect #1 from the waveform library to be triggered by SLPI
406     // while the AP is in suspend mode
407     // For default setting, we will enable this feature if that project did not
408     // set the lptrigger config
409     mHwCal->getTriggerEffectSupport(&lpTrigSupport);
410     if (!mHwApi->setLpTriggerEffect(lpTrigSupport)) {
411         ALOGW("Failed to set LP trigger mode (%d): %s", errno, strerror(errno));
412     }
413 }
414 
getCapabilities(int32_t * _aidl_return)415 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) {
416     ATRACE_NAME("Vibrator::getCapabilities");
417     int32_t ret = 0;
418     if (mHwApi->hasRtpInput()) {
419         ret |= IVibrator::CAP_AMPLITUDE_CONTROL;
420     }
421     ret |= IVibrator::CAP_GET_RESONANT_FREQUENCY;
422     *_aidl_return = ret;
423     return ndk::ScopedAStatus::ok();
424 }
425 
on(uint32_t timeoutMs,const char mode[],const std::unique_ptr<VibrationConfig> & config,const int8_t volOffset)426 ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, const char mode[],
427                                 const std::unique_ptr<VibrationConfig> &config,
428                                 const int8_t volOffset) {
429     LoopControl loopMode = LoopControl::OPEN;
430 
431     // Open-loop mode is used for short click for over-drive
432     // Close-loop mode is used for long notification for stability
433     if (mode == RTP_MODE && timeoutMs > mCloseLoopThreshold) {
434         loopMode = LoopControl::CLOSE;
435     }
436 
437     mHwApi->setCtrlLoop(toUnderlying(loopMode));
438     if (!mHwApi->setDuration(timeoutMs)) {
439         ALOGE("Failed to set duration (%d): %s", errno, strerror(errno));
440         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
441     }
442 
443     mHwApi->setMode(mode);
444     if (config != nullptr) {
445         mHwApi->setLraWaveShape(toUnderlying(config->shape));
446         mHwApi->setOdClamp(config->odClamp[volOffset]);
447         mHwApi->setOlLraPeriod(config->olLraPeriod);
448     }
449 
450     if (!mHwApi->setActivate(1)) {
451         ALOGE("Failed to activate (%d): %s", errno, strerror(errno));
452         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
453     }
454 
455     return ndk::ScopedAStatus::ok();
456 }
457 
on(int32_t timeoutMs,const std::shared_ptr<IVibratorCallback> & callback)458 ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
459                                 const std::shared_ptr<IVibratorCallback> &callback) {
460     ATRACE_NAME("Vibrator::on");
461 
462     if (callback) {
463         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
464     }
465 
466     if (mDynamicConfig) {
467         int temperature = 0;
468         mHwApi->getPATemp(&temperature);
469         if (temperature > TEMP_UPPER_BOUND) {
470             mSteadyConfig->odClamp = &mSteadyTargetOdClamp[0];
471             mSteadyConfig->olLraPeriod = mSteadyOlLraPeriod;
472 #if (VIBRATOR_FACTORY_MODE)
473             // In facotry mode, we skip motionAwareness feature.
474 #else
475             if (ENABLE_MOTION_AWARENESS(timeoutMs) && (!motionAwareness())) {
476                 return on(timeoutMs, RTP_MODE, mSteadyConfig, 2);
477             }
478 #endif
479         } else if (temperature < TEMP_LOWER_BOUND) {
480             mSteadyConfig->odClamp = &STEADY_VOLTAGE_LOWER_BOUND;
481             mSteadyConfig->olLraPeriod = mSteadyOlLraPeriodShift;
482         }
483     }
484 
485     return on(timeoutMs, RTP_MODE, mSteadyConfig, 0);
486 }
487 
off()488 ndk::ScopedAStatus Vibrator::off() {
489     ATRACE_NAME("Vibrator::off");
490     if (!mHwApi->setActivate(0)) {
491         ALOGE("Failed to turn vibrator off (%d): %s", errno, strerror(errno));
492         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
493     }
494     return ndk::ScopedAStatus::ok();
495 }
496 
setAmplitude(float amplitude)497 ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
498     ATRACE_NAME("Vibrator::setAmplitude");
499     if (amplitude <= 0.0f || amplitude > 1.0f) {
500         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
501     }
502 
503     int32_t rtp_input = std::round(amplitude * (MAX_RTP_INPUT - MIN_RTP_INPUT) + MIN_RTP_INPUT);
504 
505     if (!mHwApi->setRtpInput(rtp_input)) {
506         ALOGE("Failed to set amplitude (%d): %s", errno, strerror(errno));
507         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
508     }
509 
510     return ndk::ScopedAStatus::ok();
511 }
512 
setExternalControl(bool enabled)513 ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
514     ATRACE_NAME("Vibrator::setExternalControl");
515     ALOGE("Not support in DRV2624 solution, %d", enabled);
516     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
517 }
518 
dump(int fd,const char ** args,uint32_t numArgs)519 binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
520     if (fd < 0) {
521         ALOGE("Called debug() with invalid fd.");
522         return STATUS_OK;
523     }
524 
525     (void)args;
526     (void)numArgs;
527 
528     dprintf(fd, "AIDL:\n");
529 
530     dprintf(fd, "  Close Loop Thresh: %" PRIu32 "\n", mCloseLoopThreshold);
531     if (mSteadyConfig) {
532         dprintf(fd, "  Steady Shape: %" PRIu32 "\n", mSteadyConfig->shape);
533         dprintf(fd, "  Steady OD Clamp: %" PRIu32 " %" PRIu32 " %" PRIu32 "\n",
534                 mSteadyConfig->odClamp[0], mSteadyConfig->odClamp[1], mSteadyConfig->odClamp[2]);
535         dprintf(fd, "  Steady target G: %f %f %f\n", STEADY_TARGET_G[0],
536                 STEADY_TARGET_G[1], STEADY_TARGET_G[2]);
537         dprintf(fd, "  Steady OL LRA Period: %" PRIu32 "\n", mSteadyConfig->olLraPeriod);
538     }
539     if (mEffectConfig) {
540         dprintf(fd, "  Effect Shape: %" PRIu32 "\n", mEffectConfig->shape);
541         dprintf(fd,
542                 "  Effect OD Clamp: %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 "\n",
543                 mEffectConfig->odClamp[0], mEffectConfig->odClamp[1], mEffectConfig->odClamp[2],
544                 mEffectConfig->odClamp[3], mEffectConfig->odClamp[4]);
545         dprintf(fd, "  Effect target G: %f %f %f %f %f\n", EFFECT_TARGET_G[0],
546                 EFFECT_TARGET_G[1], EFFECT_TARGET_G[2], EFFECT_TARGET_G[3],
547                 EFFECT_TARGET_G[4]);
548         dprintf(fd, "  Effect OL LRA Period: %" PRIu32 "\n", mEffectConfig->olLraPeriod);
549     }
550     dprintf(fd, "  Click Duration: %" PRIu32 "\n", mClickDuration);
551     dprintf(fd, "  Tick Duration: %" PRIu32 "\n", mTickDuration);
552     dprintf(fd, "  Double Click Duration: %" PRIu32 "\n", mDoubleClickDuration);
553     dprintf(fd, "  Heavy Click Duration: %" PRIu32 "\n", mHeavyClickDuration);
554 
555     dprintf(fd, "\n");
556 
557     mHwApi->debug(fd);
558 
559     dprintf(fd, "\n");
560 
561     mHwCal->debug(fd);
562 
563     fsync(fd);
564     return STATUS_OK;
565 }
566 
getSupportedEffects(std::vector<Effect> * _aidl_return)567 ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect> *_aidl_return) {
568     *_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK,
569                      Effect::DOUBLE_CLICK};
570     return ndk::ScopedAStatus::ok();
571 }
572 
perform(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * _aidl_return)573 ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
574                                      const std::shared_ptr<IVibratorCallback> &callback,
575                                      int32_t *_aidl_return) {
576     ATRACE_NAME("Vibrator::perform");
577     ndk::ScopedAStatus status;
578 
579     if (callback) {
580         status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
581     } else {
582         status = performEffect(effect, strength, _aidl_return);
583     }
584 
585     return status;
586 }
587 
performEffect(Effect effect,EffectStrength strength,int32_t * outTimeMs)588 ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strength,
589                                            int32_t *outTimeMs) {
590     ndk::ScopedAStatus status;
591     uint32_t timeMS;
592     int8_t volOffset;
593 
594     switch (strength) {
595         case EffectStrength::LIGHT:
596             volOffset = 0;
597             break;
598         case EffectStrength::MEDIUM:
599             volOffset = 1;
600             break;
601         case EffectStrength::STRONG:
602             volOffset = 1;
603             break;
604         default:
605             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
606             break;
607     }
608 
609     switch (effect) {
610         case Effect::TEXTURE_TICK:
611             mHwApi->setSequencer(WAVEFORM_TICK_EFFECT_SEQ);
612             timeMS = mTickDuration;
613             volOffset = TEXTURE_TICK;
614             break;
615         case Effect::CLICK:
616             mHwApi->setSequencer(WAVEFORM_CLICK_EFFECT_SEQ);
617             timeMS = mClickDuration;
618             volOffset += CLICK;
619             break;
620         case Effect::DOUBLE_CLICK:
621             mHwApi->setSequencer(WAVEFORM_DOUBLE_CLICK_EFFECT_SEQ);
622             timeMS = mDoubleClickDuration;
623             volOffset += CLICK;
624             break;
625         case Effect::TICK:
626             mHwApi->setSequencer(WAVEFORM_TICK_EFFECT_SEQ);
627             timeMS = mTickDuration;
628             volOffset += TICK;
629             break;
630         case Effect::HEAVY_CLICK:
631             mHwApi->setSequencer(WAVEFORM_HEAVY_CLICK_EFFECT_SEQ);
632             timeMS = mHeavyClickDuration;
633             volOffset += HEAVY_CLICK;
634             break;
635         default:
636             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
637     }
638     status = on(timeMS, WAVEFORM_MODE, mEffectConfig, volOffset);
639     if (!status.isOk()) {
640         return status;
641     }
642 
643     *outTimeMs = timeMS;
644 
645     return ndk::ScopedAStatus::ok();
646 }
647 
getSupportedAlwaysOnEffects(std::vector<Effect> *)648 ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect> * /*_aidl_return*/) {
649     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
650 }
651 
alwaysOnEnable(int32_t,Effect,EffectStrength)652 ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t /*id*/, Effect /*effect*/,
653                                             EffectStrength /*strength*/) {
654     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
655 }
alwaysOnDisable(int32_t)656 ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t /*id*/) {
657     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
658 }
659 
getCompositionDelayMax(int32_t *)660 ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t * /*maxDelayMs*/) {
661     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
662 }
663 
getCompositionSizeMax(int32_t *)664 ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t * /*maxSize*/) {
665     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
666 }
667 
getSupportedPrimitives(std::vector<CompositePrimitive> *)668 ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive> * /*supported*/) {
669     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
670 }
671 
getPrimitiveDuration(CompositePrimitive,int32_t *)672 ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive /*primitive*/,
673                                                   int32_t * /*durationMs*/) {
674     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
675 }
676 
compose(const std::vector<CompositeEffect> &,const std::shared_ptr<IVibratorCallback> &)677 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> & /*composite*/,
678                                      const std::shared_ptr<IVibratorCallback> & /*callback*/) {
679     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
680 }
681 
freqPeriodFormulaFloat(std::uint32_t in)682 static float freqPeriodFormulaFloat(std::uint32_t in) {
683     return static_cast<float>(1000000000) / static_cast<float>(24615 * in);
684 }
685 
getResonantFrequency(float * resonantFreqHz)686 ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
687     uint32_t lraPeriod;
688     if(!mHwCal->getLraPeriod(&lraPeriod)) {
689         ALOGE("Failed to get resonant frequency (%d): %s", errno, strerror(errno));
690         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
691     }
692     *resonantFreqHz = freqPeriodFormulaFloat(lraPeriod);
693     return ndk::ScopedAStatus::ok();
694 }
695 
getQFactor(float *)696 ndk::ScopedAStatus Vibrator::getQFactor(float * /*qFactor*/) {
697     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
698 }
699 
getFrequencyResolution(float *)700 ndk::ScopedAStatus Vibrator::getFrequencyResolution(float * /*freqResolutionHz*/) {
701     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
702 }
703 
getFrequencyMinimum(float *)704 ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float * /*freqMinimumHz*/) {
705     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
706 }
707 
getBandwidthAmplitudeMap(std::vector<float> *)708 ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> * /*_aidl_return*/) {
709     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
710 }
711 
getPwlePrimitiveDurationMax(int32_t *)712 ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t * /*durationMs*/) {
713     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
714 }
715 
getPwleCompositionSizeMax(int32_t *)716 ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t * /*maxSize*/) {
717     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
718 }
719 
getSupportedBraking(std::vector<Braking> *)720 ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> * /*supported*/) {
721     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
722 }
723 
composePwle(const std::vector<PrimitivePwle> &,const std::shared_ptr<IVibratorCallback> &)724 ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> & /*composite*/,
725                                          const std::shared_ptr<IVibratorCallback> & /*callback*/) {
726     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
727 }
728 
729 }  // namespace vibrator
730 }  // namespace hardware
731 }  // namespace android
732 }  // namespace aidl
733