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