blob: ddc6ee0d02bd6809c495fd97aca64f043e8d7072 [file] [log] [blame]
Steven Morelandd44007e2019-10-24 18:12:46 -07001/*
2 * Copyright (C) 2019 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
Steven Moreland8ba8c032019-11-18 16:23:39 -080017#include "vibrator-impl/Vibrator.h"
Steven Morelandd44007e2019-10-24 18:12:46 -070018
19#include <android-base/logging.h>
20#include <thread>
21
22namespace aidl {
23namespace android {
24namespace hardware {
25namespace vibrator {
26
chasewu8af5e842022-03-22 01:42:24 +080027static constexpr int32_t COMPOSE_DELAY_MAX_MS = 1000;
28static constexpr int32_t COMPOSE_SIZE_MAX = 256;
29static constexpr int32_t COMPOSE_PWLE_SIZE_MAX = 127;
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +090030
chasewu8af5e842022-03-22 01:42:24 +080031static constexpr float Q_FACTOR = 11.0;
Vince Leung823cf5f2021-02-11 02:21:57 +000032static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
33static constexpr float PWLE_LEVEL_MIN = 0.0;
chasewu8af5e842022-03-22 01:42:24 +080034static constexpr float PWLE_LEVEL_MAX = 1.0;
Vince Leung823cf5f2021-02-11 02:21:57 +000035static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.0;
36static constexpr float PWLE_FREQUENCY_MIN_HZ = 140.0;
chasewu8af5e842022-03-22 01:42:24 +080037static constexpr float RESONANT_FREQUENCY_HZ = 150.0;
Vince Leung823cf5f2021-02-11 02:21:57 +000038static constexpr float PWLE_FREQUENCY_MAX_HZ = 160.0;
chasewu8af5e842022-03-22 01:42:24 +080039static constexpr float PWLE_BW_MAP_SIZE =
40 1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
Vince Leung4bae4f92021-02-03 06:21:58 +000041
Steven Morelandd44007e2019-10-24 18:12:46 -070042ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
chasewu8af5e842022-03-22 01:42:24 +080043 LOG(VERBOSE) << "Vibrator reporting capabilities";
Steven Morelandd44007e2019-10-24 18:12:46 -070044 *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
Steven Morelandc0b92d52019-11-05 13:31:41 -080045 IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
Harpreet \"Eli\" Sangha63624092019-09-09 11:04:54 +090046 IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
Vince Leung4bae4f92021-02-03 06:21:58 +000047 IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
Vince Leung823cf5f2021-02-11 02:21:57 +000048 IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL |
49 IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
Steven Morelandd44007e2019-10-24 18:12:46 -070050 return ndk::ScopedAStatus::ok();
51}
52
53ndk::ScopedAStatus Vibrator::off() {
chasewu8af5e842022-03-22 01:42:24 +080054 LOG(VERBOSE) << "Vibrator off";
Steven Morelandd44007e2019-10-24 18:12:46 -070055 return ndk::ScopedAStatus::ok();
56}
57
58ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
59 const std::shared_ptr<IVibratorCallback>& callback) {
chasewu8af5e842022-03-22 01:42:24 +080060 LOG(VERBOSE) << "Vibrator on for timeoutMs: " << timeoutMs;
Steven Morelandd44007e2019-10-24 18:12:46 -070061 if (callback != nullptr) {
62 std::thread([=] {
chasewu8af5e842022-03-22 01:42:24 +080063 LOG(VERBOSE) << "Starting on on another thread";
Steven Morelandd44007e2019-10-24 18:12:46 -070064 usleep(timeoutMs * 1000);
chasewu8af5e842022-03-22 01:42:24 +080065 LOG(VERBOSE) << "Notifying on complete";
Steven Morelandf57ad9b2019-11-27 16:04:52 -080066 if (!callback->onComplete().isOk()) {
67 LOG(ERROR) << "Failed to call onComplete";
68 }
Steven Morelandd44007e2019-10-24 18:12:46 -070069 }).detach();
70 }
71 return ndk::ScopedAStatus::ok();
72}
73
74ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
75 const std::shared_ptr<IVibratorCallback>& callback,
76 int32_t* _aidl_return) {
chasewu8af5e842022-03-22 01:42:24 +080077 LOG(VERBOSE) << "Vibrator perform";
Steven Morelandd44007e2019-10-24 18:12:46 -070078
79 if (effect != Effect::CLICK && effect != Effect::TICK) {
80 return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
81 }
82 if (strength != EffectStrength::LIGHT && strength != EffectStrength::MEDIUM &&
83 strength != EffectStrength::STRONG) {
84 return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
85 }
86
87 constexpr size_t kEffectMillis = 100;
88
89 if (callback != nullptr) {
90 std::thread([=] {
chasewu8af5e842022-03-22 01:42:24 +080091 LOG(VERBOSE) << "Starting perform on another thread";
Steven Morelandd44007e2019-10-24 18:12:46 -070092 usleep(kEffectMillis * 1000);
chasewu8af5e842022-03-22 01:42:24 +080093 LOG(VERBOSE) << "Notifying perform complete";
Steven Morelandd44007e2019-10-24 18:12:46 -070094 callback->onComplete();
95 }).detach();
96 }
97
98 *_aidl_return = kEffectMillis;
99 return ndk::ScopedAStatus::ok();
100}
101
Steven Moreland2932b222019-11-05 14:30:17 -0800102ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
103 *_aidl_return = {Effect::CLICK, Effect::TICK};
104 return ndk::ScopedAStatus::ok();
105}
106
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900107ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
chasewu8af5e842022-03-22 01:42:24 +0800108 LOG(VERBOSE) << "Vibrator set amplitude: " << amplitude;
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900109 if (amplitude <= 0.0f || amplitude > 1.0f) {
Steven Morelandd44007e2019-10-24 18:12:46 -0700110 return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
111 }
112 return ndk::ScopedAStatus::ok();
113}
114
115ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
chasewu8af5e842022-03-22 01:42:24 +0800116 LOG(VERBOSE) << "Vibrator set external control: " << enabled;
Steven Morelandd44007e2019-10-24 18:12:46 -0700117 return ndk::ScopedAStatus::ok();
118}
119
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900120ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* maxDelayMs) {
chasewu8af5e842022-03-22 01:42:24 +0800121 *maxDelayMs = COMPOSE_DELAY_MAX_MS;
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900122 return ndk::ScopedAStatus::ok();
123}
124
125ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* maxSize) {
chasewu8af5e842022-03-22 01:42:24 +0800126 *maxSize = COMPOSE_SIZE_MAX;
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900127 return ndk::ScopedAStatus::ok();
128}
129
Harpreet \"Eli\" Sangha523e2962020-01-21 16:15:42 +0900130ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive>* supported) {
131 *supported = {
132 CompositePrimitive::NOOP, CompositePrimitive::CLICK,
133 CompositePrimitive::THUD, CompositePrimitive::SPIN,
134 CompositePrimitive::QUICK_RISE, CompositePrimitive::SLOW_RISE,
Harpreet \"Eli\" Sanghafe5d3982020-01-17 14:46:37 +0900135 CompositePrimitive::QUICK_FALL, CompositePrimitive::LIGHT_TICK,
Vince Leungdeb46ec2020-12-22 00:03:16 +0000136 CompositePrimitive::LOW_TICK,
Harpreet \"Eli\" Sangha523e2962020-01-21 16:15:42 +0900137 };
138 return ndk::ScopedAStatus::ok();
139}
140
141ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
142 int32_t* durationMs) {
Lais Andrade3c7f0d92021-06-16 10:20:09 +0000143 std::vector<CompositePrimitive> supported;
144 getSupportedPrimitives(&supported);
145 if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
146 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
147 }
Harpreet \"Eli\" Sangha523e2962020-01-21 16:15:42 +0900148 if (primitive != CompositePrimitive::NOOP) {
149 *durationMs = 100;
150 } else {
151 *durationMs = 0;
152 }
153 return ndk::ScopedAStatus::ok();
154}
155
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900156ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& composite,
157 const std::shared_ptr<IVibratorCallback>& callback) {
chasewu8af5e842022-03-22 01:42:24 +0800158 if (composite.size() > COMPOSE_SIZE_MAX) {
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900159 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
160 }
161
Harpreet \"Eli\" Sangha13ef28c2020-01-23 13:22:07 +0900162 std::vector<CompositePrimitive> supported;
163 getSupportedPrimitives(&supported);
164
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900165 for (auto& e : composite) {
chasewu8af5e842022-03-22 01:42:24 +0800166 if (e.delayMs > COMPOSE_DELAY_MAX_MS) {
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900167 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
168 }
Harpreet \"Eli\" Sangha7aec5022020-03-11 06:00:55 +0900169 if (e.scale < 0.0f || e.scale > 1.0f) {
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900170 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
171 }
Harpreet \"Eli\" Sangha13ef28c2020-01-23 13:22:07 +0900172 if (std::find(supported.begin(), supported.end(), e.primitive) == supported.end()) {
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900173 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
174 }
175 }
176
177 std::thread([=] {
chasewu8af5e842022-03-22 01:42:24 +0800178 LOG(VERBOSE) << "Starting compose on another thread";
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900179
180 for (auto& e : composite) {
181 if (e.delayMs) {
182 usleep(e.delayMs * 1000);
183 }
chasewu8af5e842022-03-22 01:42:24 +0800184 LOG(VERBOSE) << "triggering primitive " << static_cast<int>(e.primitive) << " @ scale "
185 << e.scale;
Harpreet \"Eli\" Sanghab075a6a2020-04-10 15:11:58 +0900186
187 int32_t durationMs;
188 getPrimitiveDuration(e.primitive, &durationMs);
189 usleep(durationMs * 1000);
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900190 }
191
192 if (callback != nullptr) {
chasewu8af5e842022-03-22 01:42:24 +0800193 LOG(VERBOSE) << "Notifying perform complete";
Harpreet \"Eli\" Sanghaf4de5b02019-10-23 09:25:52 +0900194 callback->onComplete();
195 }
196 }).detach();
197
198 return ndk::ScopedAStatus::ok();
199}
200
Harpreet \"Eli\" Sangha63624092019-09-09 11:04:54 +0900201ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return) {
202 return getSupportedEffects(_aidl_return);
203}
204
205ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
206 std::vector<Effect> effects;
207 getSupportedAlwaysOnEffects(&effects);
208
209 if (std::find(effects.begin(), effects.end(), effect) == effects.end()) {
210 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
211 } else {
chasewu8af5e842022-03-22 01:42:24 +0800212 LOG(VERBOSE) << "Enabling always-on ID " << id << " with " << toString(effect) << "/"
213 << toString(strength);
Harpreet \"Eli\" Sangha63624092019-09-09 11:04:54 +0900214 return ndk::ScopedAStatus::ok();
215 }
216}
217
218ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t id) {
chasewu8af5e842022-03-22 01:42:24 +0800219 LOG(VERBOSE) << "Disabling always-on ID " << id;
Harpreet \"Eli\" Sangha63624092019-09-09 11:04:54 +0900220 return ndk::ScopedAStatus::ok();
221}
222
Vince Leung4bae4f92021-02-03 06:21:58 +0000223ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
chasewu8af5e842022-03-22 01:42:24 +0800224 *resonantFreqHz = RESONANT_FREQUENCY_HZ;
Vince Leung4bae4f92021-02-03 06:21:58 +0000225 return ndk::ScopedAStatus::ok();
226}
227
228ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
chasewu8af5e842022-03-22 01:42:24 +0800229 *qFactor = Q_FACTOR;
Vince Leung4bae4f92021-02-03 06:21:58 +0000230 return ndk::ScopedAStatus::ok();
231}
232
Vince Leung823cf5f2021-02-11 02:21:57 +0000233ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
234 *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
235 return ndk::ScopedAStatus::ok();
236}
237
238ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
239 *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
240 return ndk::ScopedAStatus::ok();
241}
242
243ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
chasewu8af5e842022-03-22 01:42:24 +0800244 // The output BandwidthAmplitudeMap will be as below and the maximum
245 // amplitude 1.0 will be set on RESONANT_FREQUENCY_HZ
246 // {0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1, 0.99, 0.98, 0.97,
247 // 0.96, 0.95, 0.94, 0.93, 0.92, 0.91, 0.9}
248 int32_t capabilities = 0;
249 int halfMapSize = PWLE_BW_MAP_SIZE / 2;
250 Vibrator::getCapabilities(&capabilities);
251 if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
252 std::vector<float> bandwidthAmplitudeMap(PWLE_BW_MAP_SIZE, PWLE_LEVEL_MAX);
253 for (int i = 0; i < halfMapSize; ++i) {
254 bandwidthAmplitudeMap[halfMapSize + i + 1] =
255 bandwidthAmplitudeMap[halfMapSize + i] - 0.01;
256 bandwidthAmplitudeMap[halfMapSize - i - 1] =
257 bandwidthAmplitudeMap[halfMapSize - i] - 0.01;
258 }
259 *_aidl_return = bandwidthAmplitudeMap;
260 return ndk::ScopedAStatus::ok();
261 } else {
262 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
263 }
Vince Leung823cf5f2021-02-11 02:21:57 +0000264}
265
266ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
267 *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
268 return ndk::ScopedAStatus::ok();
269}
270
271ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
chasewu8af5e842022-03-22 01:42:24 +0800272 *maxSize = COMPOSE_PWLE_SIZE_MAX;
Vince Leung823cf5f2021-02-11 02:21:57 +0000273 return ndk::ScopedAStatus::ok();
274}
275
276ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
277 *supported = {
278 Braking::NONE,
279 Braking::CLAB,
280 };
281 return ndk::ScopedAStatus::ok();
282}
283
284void resetPreviousEndAmplitudeEndFrequency(float &prevEndAmplitude, float &prevEndFrequency) {
285 const float reset = -1.0;
286 prevEndAmplitude = reset;
287 prevEndFrequency = reset;
288}
289
290void incrementIndex(int &index) {
291 index += 1;
292}
293
294void constructActiveDefaults(std::ostringstream &pwleBuilder, const int &segmentIdx) {
295 pwleBuilder << ",C" << segmentIdx << ":1";
296 pwleBuilder << ",B" << segmentIdx << ":0";
297 pwleBuilder << ",AR" << segmentIdx << ":0";
298 pwleBuilder << ",V" << segmentIdx << ":0";
299}
300
301void constructActiveSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration,
302 float amplitude, float frequency) {
303 pwleBuilder << ",T" << segmentIdx << ":" << duration;
304 pwleBuilder << ",L" << segmentIdx << ":" << amplitude;
305 pwleBuilder << ",F" << segmentIdx << ":" << frequency;
306 constructActiveDefaults(pwleBuilder, segmentIdx);
307}
308
309void constructBrakingSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration,
310 Braking brakingType) {
311 pwleBuilder << ",T" << segmentIdx << ":" << duration;
312 pwleBuilder << ",L" << segmentIdx << ":" << 0;
313 pwleBuilder << ",F" << segmentIdx << ":" << 0;
314 pwleBuilder << ",C" << segmentIdx << ":0";
315 pwleBuilder << ",B" << segmentIdx << ":"
316 << static_cast<std::underlying_type<Braking>::type>(brakingType);
317 pwleBuilder << ",AR" << segmentIdx << ":0";
318 pwleBuilder << ",V" << segmentIdx << ":0";
319}
320
321ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
322 const std::shared_ptr<IVibratorCallback> &callback) {
323 std::ostringstream pwleBuilder;
324 std::string pwleQueue;
325
326 int compositionSizeMax;
327 getPwleCompositionSizeMax(&compositionSizeMax);
328 if (composite.size() <= 0 || composite.size() > compositionSizeMax) {
329 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
330 }
331
332 float prevEndAmplitude;
333 float prevEndFrequency;
334 resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
335
336 int segmentIdx = 0;
337 uint32_t totalDuration = 0;
338
339 pwleBuilder << "S:0,WF:4,RP:0,WT:0";
340
341 for (auto &e : composite) {
342 switch (e.getTag()) {
343 case PrimitivePwle::active: {
344 auto active = e.get<PrimitivePwle::active>();
345 if (active.duration < 0 ||
346 active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
347 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
348 }
349 if (active.startAmplitude < PWLE_LEVEL_MIN ||
350 active.startAmplitude > PWLE_LEVEL_MAX ||
351 active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
352 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
353 }
354 if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
355 active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
356 active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
357 active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
358 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
359 }
360
361 if (!((active.startAmplitude == prevEndAmplitude) &&
362 (active.startFrequency == prevEndFrequency))) {
363 constructActiveSegment(pwleBuilder, segmentIdx, 0, active.startAmplitude,
364 active.startFrequency);
365 incrementIndex(segmentIdx);
366 }
367
368 constructActiveSegment(pwleBuilder, segmentIdx, active.duration,
369 active.endAmplitude, active.endFrequency);
370 incrementIndex(segmentIdx);
371
372 prevEndAmplitude = active.endAmplitude;
373 prevEndFrequency = active.endFrequency;
374 totalDuration += active.duration;
375 break;
376 }
377 case PrimitivePwle::braking: {
378 auto braking = e.get<PrimitivePwle::braking>();
379 if (braking.braking > Braking::CLAB) {
380 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
381 }
382 if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
383 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
384 }
385
386 constructBrakingSegment(pwleBuilder, segmentIdx, 0, braking.braking);
387 incrementIndex(segmentIdx);
388
389 constructBrakingSegment(pwleBuilder, segmentIdx, braking.duration, braking.braking);
390 incrementIndex(segmentIdx);
391
392 resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
393 totalDuration += braking.duration;
394 break;
395 }
396 }
397 }
398
399 std::thread([=] {
chasewu8af5e842022-03-22 01:42:24 +0800400 LOG(VERBOSE) << "Starting composePwle on another thread";
Vince Leung823cf5f2021-02-11 02:21:57 +0000401 usleep(totalDuration * 1000);
402 if (callback != nullptr) {
chasewu8af5e842022-03-22 01:42:24 +0800403 LOG(VERBOSE) << "Notifying compose PWLE complete";
Vince Leung823cf5f2021-02-11 02:21:57 +0000404 callback->onComplete();
405 }
406 }).detach();
407
408 return ndk::ScopedAStatus::ok();
409}
410
Steven Morelandd44007e2019-10-24 18:12:46 -0700411} // namespace vibrator
412} // namespace hardware
413} // namespace android
414} // namespace aidl