blob: b96e06da5b439b90b3fd61d4f124a4514b46b5ef [file] [log] [blame]
Lais Andradee29acd82020-08-07 13:21:17 +00001/*
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
17#include "benchmark/benchmark.h"
18
19#include <android/hardware/vibrator/1.3/IVibrator.h>
20#include <android/hardware/vibrator/BnVibratorCallback.h>
21#include <android/hardware/vibrator/IVibrator.h>
22#include <binder/IServiceManager.h>
23
24using ::android::enum_range;
25using ::android::sp;
26using ::android::hardware::hidl_enum_range;
27using ::android::hardware::Return;
28using ::android::hardware::details::hidl_enum_values;
29using ::benchmark::Counter;
30using ::benchmark::Fixture;
31using ::benchmark::kMicrosecond;
32using ::benchmark::State;
33using ::benchmark::internal::Benchmark;
34using ::std::chrono::duration;
35using ::std::chrono::duration_cast;
36using ::std::chrono::high_resolution_clock;
37
38namespace Aidl = ::android::hardware::vibrator;
39namespace V1_0 = ::android::hardware::vibrator::V1_0;
40namespace V1_1 = ::android::hardware::vibrator::V1_1;
41namespace V1_2 = ::android::hardware::vibrator::V1_2;
42namespace V1_3 = ::android::hardware::vibrator::V1_3;
43
44template <typename I>
45class BaseBench : public Fixture {
46 public:
47 void TearDown(State& /*state*/) override {
48 if (!mVibrator) {
49 return;
50 }
51 mVibrator->off();
52 }
53
54 static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
55
56 static void DefaultArgs(Benchmark* /*b*/) { /* none */
57 }
58
59 protected:
60 auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
61
62 protected:
63 sp<I> mVibrator;
64};
65
66template <typename I>
67class VibratorBench : public BaseBench<I> {
68 public:
69 void SetUp(State& /*state*/) override { this->mVibrator = I::getService(); }
70};
71
72enum class EmptyEnum : uint32_t;
73template <>
74inline constexpr std::array<EmptyEnum, 0> hidl_enum_values<EmptyEnum> = {};
75
76template <typename T, typename U>
77std::set<T> difference(const hidl_enum_range<T>& t, const hidl_enum_range<U>& u) {
78 class Compare {
79 public:
80 bool operator()(const T& a, const U& b) { return a < static_cast<T>(b); }
81 bool operator()(const U& a, const T& b) { return static_cast<T>(a) < b; }
82 };
83 std::set<T> ret;
84
85 std::set_difference(t.begin(), t.end(), u.begin(), u.end(),
86 std::insert_iterator<decltype(ret)>(ret, ret.begin()), Compare());
87
88 return ret;
89}
90
91template <typename I, typename E1, typename E2 = EmptyEnum>
92class VibratorEffectsBench : public VibratorBench<I> {
93 public:
94 using Effect = E1;
95 using EffectStrength = V1_0::EffectStrength;
96 using Status = V1_0::Status;
97
98 public:
99 static void DefaultArgs(Benchmark* b) {
100 b->ArgNames({"Effect", "Strength"});
101 for (const auto& effect : difference(hidl_enum_range<E1>(), hidl_enum_range<E2>())) {
102 for (const auto& strength : hidl_enum_range<EffectStrength>()) {
103 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
104 }
105 }
106 }
107
108 void performBench(State* state, Return<void> (I::*performApi)(Effect, EffectStrength,
109 typename I::perform_cb)) {
110 auto effect = getEffect(*state);
111 auto strength = getStrength(*state);
112 bool supported = true;
113
114 (*this->mVibrator.*performApi)(effect, strength, [&](Status status, uint32_t /*lengthMs*/) {
115 if (status == Status::UNSUPPORTED_OPERATION) {
116 supported = false;
117 }
118 });
119
120 if (!supported) {
Adrian Roos77659422024-02-09 17:20:54 +0000121 state->SkipWithMessage("performApi returned UNSUPPORTED_OPERATION");
Lais Andradee29acd82020-08-07 13:21:17 +0000122 return;
123 }
124
125 for (auto _ : *state) {
126 state->ResumeTiming();
127 (*this->mVibrator.*performApi)(effect, strength,
128 [](Status /*status*/, uint32_t /*lengthMs*/) {});
129 state->PauseTiming();
130 this->mVibrator->off();
131 }
132 }
133
134 protected:
135 auto getEffect(const State& state) const {
136 return static_cast<Effect>(this->getOtherArg(state, 0));
137 }
138
139 auto getStrength(const State& state) const {
140 return static_cast<EffectStrength>(this->getOtherArg(state, 1));
141 }
142};
143
Adrian Roos77659422024-02-09 17:20:54 +0000144#define BENCHMARK_WRAPPER(fixt, test, code) \
145 BENCHMARK_DEFINE_F(fixt, test) \
146 /* NOLINTNEXTLINE */ \
147 (State & state) { \
148 if (!mVibrator) { \
149 state.SkipWithMessage("HAL unavailable"); \
150 return; \
151 } \
152 \
153 code \
154 } \
Lais Andradee29acd82020-08-07 13:21:17 +0000155 BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs)
156
157using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>;
158
159BENCHMARK_WRAPPER(VibratorBench_V1_0, on, {
160 uint32_t ms = UINT32_MAX;
161
162 for (auto _ : state) {
163 state.ResumeTiming();
164 mVibrator->on(ms);
165 state.PauseTiming();
166 mVibrator->off();
167 }
168});
169
170BENCHMARK_WRAPPER(VibratorBench_V1_0, off, {
171 uint32_t ms = UINT32_MAX;
172
173 for (auto _ : state) {
174 state.PauseTiming();
175 mVibrator->on(ms);
176 state.ResumeTiming();
177 mVibrator->off();
178 }
179});
180
181BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, {
182 for (auto _ : state) {
183 mVibrator->supportsAmplitudeControl();
184 }
185});
186
187BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, {
188 uint8_t amplitude = UINT8_MAX;
189
190 if (!mVibrator->supportsAmplitudeControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000191 state.SkipWithMessage("Amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000192 return;
193 }
194
195 mVibrator->on(UINT32_MAX);
196
197 for (auto _ : state) {
198 mVibrator->setAmplitude(amplitude);
199 }
200
201 mVibrator->off();
202});
203
204using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>;
205
206BENCHMARK_WRAPPER(VibratorEffectsBench_V1_0, perform,
207 { performBench(&state, &V1_0::IVibrator::perform); });
208
209using VibratorEffectsBench_V1_1 =
210 VibratorEffectsBench<V1_1::IVibrator, V1_1::Effect_1_1, V1_0::Effect>;
211
212BENCHMARK_WRAPPER(VibratorEffectsBench_V1_1, perform_1_1,
213 { performBench(&state, &V1_1::IVibrator::perform_1_1); });
214
215using VibratorEffectsBench_V1_2 =
216 VibratorEffectsBench<V1_2::IVibrator, V1_2::Effect, V1_1::Effect_1_1>;
217
218BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2,
219 { performBench(&state, &V1_2::IVibrator::perform_1_2); });
220
221using VibratorBench_V1_3 = VibratorBench<V1_3::IVibrator>;
222
223BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, {
224 for (auto _ : state) {
225 mVibrator->supportsExternalControl();
226 }
227});
228
229BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, {
230 bool enable = true;
231
232 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000233 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000234 return;
235 }
236
237 for (auto _ : state) {
238 state.ResumeTiming();
239 mVibrator->setExternalControl(enable);
240 state.PauseTiming();
241 mVibrator->setExternalControl(false);
242 }
243});
244
245BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, {
246 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000247 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000248 return;
249 }
250
251 mVibrator->setExternalControl(true);
252
253 for (auto _ : state) {
254 mVibrator->supportsAmplitudeControl();
255 }
256
257 mVibrator->setExternalControl(false);
258});
259
260BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, {
261 uint8_t amplitude = UINT8_MAX;
262
263 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000264 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000265 return;
266 }
267
268 mVibrator->setExternalControl(true);
269
270 if (!mVibrator->supportsAmplitudeControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000271 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000272 return;
273 }
274
275 for (auto _ : state) {
276 mVibrator->setAmplitude(amplitude);
277 }
278
279 mVibrator->setExternalControl(false);
280});
281
282using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>;
283
284BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3,
285 { performBench(&state, &V1_3::IVibrator::perform_1_3); });
286
287class VibratorBench_Aidl : public BaseBench<Aidl::IVibrator> {
288 public:
289 void SetUp(State& /*state*/) override {
290 this->mVibrator = android::waitForVintfService<Aidl::IVibrator>();
291 }
292};
293
294class HalCallback : public Aidl::BnVibratorCallback {
295 public:
296 HalCallback() = default;
297 ~HalCallback() = default;
298
299 android::binder::Status onComplete() override { return android::binder::Status::ok(); }
300};
301
302BENCHMARK_WRAPPER(VibratorBench_Aidl, on, {
303 int32_t capabilities = 0;
304 mVibrator->getCapabilities(&capabilities);
305
306 int32_t ms = INT32_MAX;
307 auto cb = (capabilities & Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
308
309 for (auto _ : state) {
310 state.ResumeTiming();
311 mVibrator->on(ms, cb);
312 state.PauseTiming();
313 mVibrator->off();
314 }
315});
316
317BENCHMARK_WRAPPER(VibratorBench_Aidl, off, {
318 for (auto _ : state) {
319 state.PauseTiming();
320 mVibrator->on(INT32_MAX, nullptr);
321 state.ResumeTiming();
322 mVibrator->off();
323 }
324});
325
326BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, {
327 int32_t capabilities = 0;
328
329 for (auto _ : state) {
330 mVibrator->getCapabilities(&capabilities);
331 }
332});
333
334BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, {
335 int32_t capabilities = 0;
336 mVibrator->getCapabilities(&capabilities);
337 if ((capabilities & Aidl::IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
Adrian Roos77659422024-02-09 17:20:54 +0000338 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000339 return;
340 }
341
342 float amplitude = 1.0f;
343 mVibrator->on(INT32_MAX, nullptr);
344
345 for (auto _ : state) {
346 mVibrator->setAmplitude(amplitude);
347 }
348
349 mVibrator->off();
350});
351
352BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, {
353 int32_t capabilities = 0;
354 mVibrator->getCapabilities(&capabilities);
355 if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
Adrian Roos77659422024-02-09 17:20:54 +0000356 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000357 return;
358 }
359
360 for (auto _ : state) {
361 state.ResumeTiming();
362 mVibrator->setExternalControl(true);
363 state.PauseTiming();
364 mVibrator->setExternalControl(false);
365 }
366});
367
368BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, {
369 int32_t capabilities = 0;
370 mVibrator->getCapabilities(&capabilities);
371 if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0 ||
372 (capabilities & Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) == 0) {
Adrian Roos77659422024-02-09 17:20:54 +0000373 state.SkipWithMessage("external amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000374 return;
375 }
376
377 float amplitude = 1.0f;
378 mVibrator->setExternalControl(true);
379
380 for (auto _ : state) {
381 mVibrator->setAmplitude(amplitude);
382 }
383
384 mVibrator->setExternalControl(false);
385});
386
387BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, {
388 std::vector<Aidl::Effect> supportedEffects;
389
390 for (auto _ : state) {
391 mVibrator->getSupportedEffects(&supportedEffects);
392 }
393});
394
395BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, {
396 std::vector<Aidl::Effect> supportedEffects;
397
398 for (auto _ : state) {
399 mVibrator->getSupportedAlwaysOnEffects(&supportedEffects);
400 }
401});
402
403BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, {
404 std::vector<Aidl::CompositePrimitive> supportedPrimitives;
405
406 for (auto _ : state) {
407 mVibrator->getSupportedPrimitives(&supportedPrimitives);
408 }
409});
410
411class VibratorEffectsBench_Aidl : public VibratorBench_Aidl {
412 public:
413 static void DefaultArgs(Benchmark* b) {
414 b->ArgNames({"Effect", "Strength"});
415 for (const auto& effect : enum_range<Aidl::Effect>()) {
416 for (const auto& strength : enum_range<Aidl::EffectStrength>()) {
417 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
418 }
419 }
420 }
421
422 protected:
423 auto getEffect(const State& state) const {
424 return static_cast<Aidl::Effect>(this->getOtherArg(state, 0));
425 }
426
427 auto getStrength(const State& state) const {
428 return static_cast<Aidl::EffectStrength>(this->getOtherArg(state, 1));
429 }
430};
431
432BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, {
433 int32_t capabilities = 0;
434 mVibrator->getCapabilities(&capabilities);
435 if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) {
Adrian Roos77659422024-02-09 17:20:54 +0000436 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000437 return;
438 }
439
440 int32_t id = 1;
441 auto effect = getEffect(state);
442 auto strength = getStrength(state);
443
444 std::vector<Aidl::Effect> supported;
445 mVibrator->getSupportedAlwaysOnEffects(&supported);
446 if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
Adrian Roos77659422024-02-09 17:20:54 +0000447 state.SkipWithMessage("always on effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000448 return;
449 }
450
451 for (auto _ : state) {
452 state.ResumeTiming();
453 mVibrator->alwaysOnEnable(id, effect, strength);
454 state.PauseTiming();
455 mVibrator->alwaysOnDisable(id);
456 }
457});
458
459BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, {
460 int32_t capabilities = 0;
461 mVibrator->getCapabilities(&capabilities);
462 if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) {
Adrian Roos77659422024-02-09 17:20:54 +0000463 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000464 return;
465 }
466
467 int32_t id = 1;
468 auto effect = getEffect(state);
469 auto strength = getStrength(state);
470
471 std::vector<Aidl::Effect> supported;
472 mVibrator->getSupportedAlwaysOnEffects(&supported);
473 if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
Adrian Roos77659422024-02-09 17:20:54 +0000474 state.SkipWithMessage("always on effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000475 return;
476 }
477
478 for (auto _ : state) {
479 state.PauseTiming();
480 mVibrator->alwaysOnEnable(id, effect, strength);
481 state.ResumeTiming();
482 mVibrator->alwaysOnDisable(id);
483 }
484});
485
486BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, perform, {
487 int32_t capabilities = 0;
488 mVibrator->getCapabilities(&capabilities);
489
490 auto effect = getEffect(state);
491 auto strength = getStrength(state);
492 auto cb = (capabilities & Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr;
493 int32_t lengthMs = 0;
494
495 std::vector<Aidl::Effect> supported;
496 mVibrator->getSupportedEffects(&supported);
497 if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
Adrian Roos77659422024-02-09 17:20:54 +0000498 state.SkipWithMessage("effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000499 return;
500 }
501
502 for (auto _ : state) {
503 state.ResumeTiming();
504 mVibrator->perform(effect, strength, cb, &lengthMs);
505 state.PauseTiming();
506 mVibrator->off();
507 }
508});
509
510class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl {
511 public:
512 static void DefaultArgs(Benchmark* b) {
513 b->ArgNames({"Primitive"});
514 for (const auto& primitive : enum_range<Aidl::CompositePrimitive>()) {
515 b->Args({static_cast<long>(primitive)});
516 }
517 }
518
519 protected:
520 auto getPrimitive(const State& state) const {
521 return static_cast<Aidl::CompositePrimitive>(this->getOtherArg(state, 0));
522 }
523};
524
525BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, {
526 int32_t ms = 0;
527
528 for (auto _ : state) {
529 mVibrator->getCompositionDelayMax(&ms);
530 }
531});
532
533BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, {
534 int32_t size = 0;
535
536 for (auto _ : state) {
537 mVibrator->getCompositionSizeMax(&size);
538 }
539});
540
541BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, {
542 int32_t capabilities = 0;
543 mVibrator->getCapabilities(&capabilities);
544 if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) {
Adrian Roos77659422024-02-09 17:20:54 +0000545 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000546 return;
547 }
548
549 auto primitive = getPrimitive(state);
550 int32_t ms = 0;
551
552 std::vector<Aidl::CompositePrimitive> supported;
553 mVibrator->getSupportedPrimitives(&supported);
554 if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
Adrian Roos77659422024-02-09 17:20:54 +0000555 state.SkipWithMessage("supported primitives unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000556 return;
557 }
558
559 for (auto _ : state) {
560 mVibrator->getPrimitiveDuration(primitive, &ms);
561 }
562});
563
564BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, {
565 int32_t capabilities = 0;
566 mVibrator->getCapabilities(&capabilities);
567 if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) {
Adrian Roos77659422024-02-09 17:20:54 +0000568 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000569 return;
570 }
571
572 Aidl::CompositeEffect effect;
573 effect.primitive = getPrimitive(state);
574 effect.scale = 1.0f;
575 effect.delayMs = 0;
576
577 std::vector<Aidl::CompositePrimitive> supported;
578 mVibrator->getSupportedPrimitives(&supported);
579 if (std::find(supported.begin(), supported.end(), effect.primitive) == supported.end()) {
Adrian Roos77659422024-02-09 17:20:54 +0000580 state.SkipWithMessage("supported primitives unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000581 return;
582 }
583
584 auto cb = new HalCallback();
585 std::vector<Aidl::CompositeEffect> effects;
586 effects.push_back(effect);
587
588 for (auto _ : state) {
589 state.ResumeTiming();
590 mVibrator->compose(effects, cb);
591 state.PauseTiming();
592 mVibrator->off();
593 }
594});
595
596BENCHMARK_MAIN();