blob: 8e8d78f8b9b8e9f0b32973504948f2029a3660ed [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>
Lais Andrade59a5d542024-03-12 11:53:00 +000023#include <binder/ProcessState.h>
24#include <future>
Lais Andradee29acd82020-08-07 13:21:17 +000025
26using ::android::enum_range;
27using ::android::sp;
28using ::android::hardware::hidl_enum_range;
29using ::android::hardware::Return;
30using ::android::hardware::details::hidl_enum_values;
31using ::benchmark::Counter;
32using ::benchmark::Fixture;
33using ::benchmark::kMicrosecond;
34using ::benchmark::State;
35using ::benchmark::internal::Benchmark;
Lais Andrade59a5d542024-03-12 11:53:00 +000036
37using namespace ::std::chrono_literals;
Lais Andradee29acd82020-08-07 13:21:17 +000038
39namespace Aidl = ::android::hardware::vibrator;
40namespace V1_0 = ::android::hardware::vibrator::V1_0;
41namespace V1_1 = ::android::hardware::vibrator::V1_1;
42namespace V1_2 = ::android::hardware::vibrator::V1_2;
43namespace V1_3 = ::android::hardware::vibrator::V1_3;
44
Lais Andrade59a5d542024-03-12 11:53:00 +000045// Fixed number of iterations for benchmarks that trigger a vibration on the loop.
46// They require slow cleanup to ensure a stable state on each run and less noisy metrics.
47static constexpr auto VIBRATION_ITERATIONS = 500;
48
49// Timeout to wait for vibration callback completion.
50static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms;
51
52// Max duration the vibrator can be turned on, in milliseconds.
53static constexpr uint32_t MAX_ON_DURATION_MS = UINT16_MAX;
54
Lais Andradee29acd82020-08-07 13:21:17 +000055template <typename I>
56class BaseBench : public Fixture {
57 public:
Lais Andrade59a5d542024-03-12 11:53:00 +000058 void SetUp(State& /*state*/) override {
59 android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
60 android::ProcessState::self()->startThreadPool();
61 }
62
Lais Andradee29acd82020-08-07 13:21:17 +000063 void TearDown(State& /*state*/) override {
Lais Andrade59a5d542024-03-12 11:53:00 +000064 if (mVibrator) {
65 mVibrator->off();
Lais Andradee29acd82020-08-07 13:21:17 +000066 }
Lais Andradee29acd82020-08-07 13:21:17 +000067 }
68
69 static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
70
71 static void DefaultArgs(Benchmark* /*b*/) { /* none */
72 }
73
74 protected:
75 auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
76
77 protected:
78 sp<I> mVibrator;
79};
80
81template <typename I>
82class VibratorBench : public BaseBench<I> {
83 public:
Lais Andrade59a5d542024-03-12 11:53:00 +000084 void SetUp(State& state) override {
85 BaseBench<I>::SetUp(state);
86 this->mVibrator = I::getService();
87 }
88
89 protected:
90 bool shouldSkipWithError(State& state, const android::hardware::Return<V1_0::Status>&& ret) {
91 if (!ret.isOk()) {
92 state.SkipWithError(ret.description());
93 return true;
94 }
95 return false;
96 }
Lais Andradee29acd82020-08-07 13:21:17 +000097};
98
99enum class EmptyEnum : uint32_t;
100template <>
101inline constexpr std::array<EmptyEnum, 0> hidl_enum_values<EmptyEnum> = {};
102
103template <typename T, typename U>
104std::set<T> difference(const hidl_enum_range<T>& t, const hidl_enum_range<U>& u) {
105 class Compare {
106 public:
107 bool operator()(const T& a, const U& b) { return a < static_cast<T>(b); }
108 bool operator()(const U& a, const T& b) { return static_cast<T>(a) < b; }
109 };
110 std::set<T> ret;
111
112 std::set_difference(t.begin(), t.end(), u.begin(), u.end(),
113 std::insert_iterator<decltype(ret)>(ret, ret.begin()), Compare());
114
115 return ret;
116}
117
118template <typename I, typename E1, typename E2 = EmptyEnum>
119class VibratorEffectsBench : public VibratorBench<I> {
120 public:
121 using Effect = E1;
122 using EffectStrength = V1_0::EffectStrength;
123 using Status = V1_0::Status;
124
125 public:
126 static void DefaultArgs(Benchmark* b) {
127 b->ArgNames({"Effect", "Strength"});
128 for (const auto& effect : difference(hidl_enum_range<E1>(), hidl_enum_range<E2>())) {
129 for (const auto& strength : hidl_enum_range<EffectStrength>()) {
130 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
131 }
132 }
133 }
134
135 void performBench(State* state, Return<void> (I::*performApi)(Effect, EffectStrength,
136 typename I::perform_cb)) {
137 auto effect = getEffect(*state);
138 auto strength = getStrength(*state);
139 bool supported = true;
140
141 (*this->mVibrator.*performApi)(effect, strength, [&](Status status, uint32_t /*lengthMs*/) {
142 if (status == Status::UNSUPPORTED_OPERATION) {
143 supported = false;
144 }
145 });
146
147 if (!supported) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000148 state->SkipWithMessage("effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000149 return;
150 }
151
152 for (auto _ : *state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000153 // Test
154 auto ret = (*this->mVibrator.*performApi)(
155 effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {});
156
157 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000158 state->PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000159 if (!ret.isOk()) {
160 state->SkipWithError(ret.description());
161 return;
162 }
163 if (this->shouldSkipWithError(*state, this->mVibrator->off())) {
164 return;
165 }
166 state->ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000167 }
168 }
169
170 protected:
171 auto getEffect(const State& state) const {
172 return static_cast<Effect>(this->getOtherArg(state, 0));
173 }
174
175 auto getStrength(const State& state) const {
176 return static_cast<EffectStrength>(this->getOtherArg(state, 1));
177 }
178};
179
Adrian Roos77659422024-02-09 17:20:54 +0000180#define BENCHMARK_WRAPPER(fixt, test, code) \
181 BENCHMARK_DEFINE_F(fixt, test) \
182 /* NOLINTNEXTLINE */ \
183 (State & state) { \
184 if (!mVibrator) { \
185 state.SkipWithMessage("HAL unavailable"); \
186 return; \
187 } \
188 \
189 code \
190 } \
Lais Andradee29acd82020-08-07 13:21:17 +0000191 BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs)
192
193using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>;
194
195BENCHMARK_WRAPPER(VibratorBench_V1_0, on, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000196 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000197
198 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000199 // Test
200 if (shouldSkipWithError(state, mVibrator->on(ms))) {
201 return;
202 }
203
204 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000205 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000206 if (shouldSkipWithError(state, mVibrator->off())) {
207 return;
208 }
209 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000210 }
211});
212
213BENCHMARK_WRAPPER(VibratorBench_V1_0, off, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000214 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000215
216 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000217 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000218 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000219 if (shouldSkipWithError(state, mVibrator->on(ms))) {
220 return;
221 }
Lais Andradee29acd82020-08-07 13:21:17 +0000222 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000223
224 // Test
225 if (shouldSkipWithError(state, mVibrator->off())) {
226 return;
227 }
Lais Andradee29acd82020-08-07 13:21:17 +0000228 }
229});
230
231BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, {
232 for (auto _ : state) {
233 mVibrator->supportsAmplitudeControl();
234 }
235});
236
237BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000238 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000239 uint8_t amplitude = UINT8_MAX;
240
241 if (!mVibrator->supportsAmplitudeControl()) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000242 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000243 return;
244 }
245
Lais Andrade59a5d542024-03-12 11:53:00 +0000246 if (shouldSkipWithError(state, mVibrator->on(ms))) {
247 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000248 }
249
Lais Andrade59a5d542024-03-12 11:53:00 +0000250 for (auto _ : state) {
251 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
252 return;
253 }
254 }
Lais Andradee29acd82020-08-07 13:21:17 +0000255});
256
257using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>;
258
259BENCHMARK_WRAPPER(VibratorEffectsBench_V1_0, perform,
260 { performBench(&state, &V1_0::IVibrator::perform); });
261
262using VibratorEffectsBench_V1_1 =
263 VibratorEffectsBench<V1_1::IVibrator, V1_1::Effect_1_1, V1_0::Effect>;
264
265BENCHMARK_WRAPPER(VibratorEffectsBench_V1_1, perform_1_1,
266 { performBench(&state, &V1_1::IVibrator::perform_1_1); });
267
268using VibratorEffectsBench_V1_2 =
269 VibratorEffectsBench<V1_2::IVibrator, V1_2::Effect, V1_1::Effect_1_1>;
270
271BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2,
272 { performBench(&state, &V1_2::IVibrator::perform_1_2); });
273
Lais Andrade59a5d542024-03-12 11:53:00 +0000274class VibratorBench_V1_3 : public VibratorBench<V1_3::IVibrator> {
275 public:
276 void TearDown(State& state) override {
277 VibratorBench::TearDown(state);
278 if (mVibrator) {
279 mVibrator->setExternalControl(false);
280 }
281 }
282};
Lais Andradee29acd82020-08-07 13:21:17 +0000283
284BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, {
285 for (auto _ : state) {
286 mVibrator->supportsExternalControl();
287 }
288});
289
290BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, {
Lais Andradee29acd82020-08-07 13:21:17 +0000291 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000292 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000293 return;
294 }
295
296 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000297 // Test
298 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
299 return;
300 }
301
302 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000303 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000304 if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
305 return;
306 }
307 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000308 }
309});
310
311BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, {
312 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000313 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000314 return;
315 }
316
Lais Andrade59a5d542024-03-12 11:53:00 +0000317 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
318 return;
319 }
Lais Andradee29acd82020-08-07 13:21:17 +0000320
321 for (auto _ : state) {
322 mVibrator->supportsAmplitudeControl();
323 }
Lais Andradee29acd82020-08-07 13:21:17 +0000324});
325
326BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, {
327 uint8_t amplitude = UINT8_MAX;
328
329 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000330 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000331 return;
332 }
333
Lais Andrade59a5d542024-03-12 11:53:00 +0000334 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
335 return;
336 }
Lais Andradee29acd82020-08-07 13:21:17 +0000337
338 if (!mVibrator->supportsAmplitudeControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000339 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000340 return;
341 }
342
343 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000344 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
345 return;
346 }
Lais Andradee29acd82020-08-07 13:21:17 +0000347 }
Lais Andradee29acd82020-08-07 13:21:17 +0000348});
349
350using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>;
351
352BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3,
353 { performBench(&state, &V1_3::IVibrator::perform_1_3); });
354
355class VibratorBench_Aidl : public BaseBench<Aidl::IVibrator> {
356 public:
Lais Andrade59a5d542024-03-12 11:53:00 +0000357 void SetUp(State& state) override {
358 BaseBench::SetUp(state);
Lais Andradee29acd82020-08-07 13:21:17 +0000359 this->mVibrator = android::waitForVintfService<Aidl::IVibrator>();
360 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000361
362 void TearDown(State& state) override {
363 BaseBench::TearDown(state);
364 if (mVibrator) {
365 mVibrator->setExternalControl(false);
366 }
367 }
368
369 protected:
370 int32_t hasCapabilities(int32_t capabilities) {
371 int32_t deviceCapabilities = 0;
372 this->mVibrator->getCapabilities(&deviceCapabilities);
373 return (deviceCapabilities & capabilities) == capabilities;
374 }
375
376 bool shouldSkipWithError(State& state, const android::binder::Status&& status) {
377 if (!status.isOk()) {
378 state.SkipWithError(status.toString8().c_str());
379 return true;
380 }
381 return false;
382 }
383
Lais Andradea5131c52024-06-12 16:39:29 +0100384 void waitForComplete(std::future<void>& callbackFuture) {
385 // Wait until the HAL has finished processing previous vibration before starting a new one,
386 // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
387 // HAL implementations are waiting on previous vibration cleanup and might be significantly
388 // slower, so make sure we measure vibrations on a clean slate.
389 if (callbackFuture.valid()) {
390 callbackFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT);
391 }
392 }
393
Lais Andrade59a5d542024-03-12 11:53:00 +0000394 static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); }
395};
396
397class SlowVibratorBench_Aidl : public VibratorBench_Aidl {
398 public:
399 static void DefaultConfig(Benchmark* b) {
400 VibratorBench_Aidl::DefaultConfig(b);
401 SlowBenchConfig(b);
402 }
Lais Andradee29acd82020-08-07 13:21:17 +0000403};
404
405class HalCallback : public Aidl::BnVibratorCallback {
406 public:
407 HalCallback() = default;
408 ~HalCallback() = default;
409
Lais Andrade59a5d542024-03-12 11:53:00 +0000410 android::binder::Status onComplete() override {
411 mPromise.set_value();
412 return android::binder::Status::ok();
413 }
414
Lais Andradea5131c52024-06-12 16:39:29 +0100415 std::future<void> getFuture() { return mPromise.get_future(); }
Lais Andrade59a5d542024-03-12 11:53:00 +0000416
417 private:
418 std::promise<void> mPromise;
Lais Andradee29acd82020-08-07 13:21:17 +0000419};
420
Lais Andrade59a5d542024-03-12 11:53:00 +0000421BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, on, {
422 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000423
424 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000425 auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100426 // Grab the future before callback promise is destroyed by the HAL.
427 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000428
429 // Test
430 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
431 return;
432 }
433
434 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000435 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000436 if (shouldSkipWithError(state, mVibrator->off())) {
437 return;
438 }
Lais Andradea5131c52024-06-12 16:39:29 +0100439 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000440 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000441 }
442});
443
Lais Andrade59a5d542024-03-12 11:53:00 +0000444BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, off, {
445 auto ms = MAX_ON_DURATION_MS;
446
Lais Andradee29acd82020-08-07 13:21:17 +0000447 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000448 auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100449 // Grab the future before callback promise is destroyed by the HAL.
450 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000451
452 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000453 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000454 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
455 return;
456 }
Lais Andradee29acd82020-08-07 13:21:17 +0000457 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000458
459 // Test
460 if (shouldSkipWithError(state, mVibrator->off())) {
461 return;
462 }
463
464 // Cleanup
465 state.PauseTiming();
Lais Andradea5131c52024-06-12 16:39:29 +0100466 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000467 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000468 }
469});
470
471BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, {
472 int32_t capabilities = 0;
473
474 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000475 if (shouldSkipWithError(state, mVibrator->getCapabilities(&capabilities))) {
476 return;
477 }
Lais Andradee29acd82020-08-07 13:21:17 +0000478 }
479});
480
481BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000482 auto ms = MAX_ON_DURATION_MS;
483 float amplitude = 1.0f;
484
485 if (!hasCapabilities(Aidl::IVibrator::CAP_AMPLITUDE_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000486 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000487 return;
488 }
489
Lais Andrade59a5d542024-03-12 11:53:00 +0000490 auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
491 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
492 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000493 }
494
Lais Andrade59a5d542024-03-12 11:53:00 +0000495 for (auto _ : state) {
496 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
497 return;
498 }
499 }
Lais Andradee29acd82020-08-07 13:21:17 +0000500});
501
502BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000503 if (!hasCapabilities(Aidl::IVibrator::CAP_EXTERNAL_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000504 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000505 return;
506 }
507
508 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000509 // Test
510 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
511 return;
512 }
513
514 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000515 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000516 if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
517 return;
518 }
519 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000520 }
521});
522
523BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000524 auto externalControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_CONTROL);
525 auto externalAmplitudeControl =
526 static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL);
527 if (!hasCapabilities(externalControl | externalAmplitudeControl)) {
Adrian Roos77659422024-02-09 17:20:54 +0000528 state.SkipWithMessage("external amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000529 return;
530 }
531
Lais Andrade59a5d542024-03-12 11:53:00 +0000532 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
533 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000534 }
535
Lais Andrade59a5d542024-03-12 11:53:00 +0000536 float amplitude = 1.0f;
537 for (auto _ : state) {
538 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
539 return;
540 }
541 }
Lais Andradee29acd82020-08-07 13:21:17 +0000542});
543
544BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, {
545 std::vector<Aidl::Effect> supportedEffects;
546
547 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000548 if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) {
549 return;
550 }
Lais Andradee29acd82020-08-07 13:21:17 +0000551 }
552});
553
554BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000555 if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
556 state.SkipWithMessage("always on control unavailable");
557 return;
558 }
559
Lais Andradee29acd82020-08-07 13:21:17 +0000560 std::vector<Aidl::Effect> supportedEffects;
561
562 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000563 if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) {
564 return;
565 }
Lais Andradee29acd82020-08-07 13:21:17 +0000566 }
567});
568
569BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, {
570 std::vector<Aidl::CompositePrimitive> supportedPrimitives;
571
572 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000573 if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) {
574 return;
575 }
Lais Andradee29acd82020-08-07 13:21:17 +0000576 }
577});
578
579class VibratorEffectsBench_Aidl : public VibratorBench_Aidl {
580 public:
581 static void DefaultArgs(Benchmark* b) {
582 b->ArgNames({"Effect", "Strength"});
583 for (const auto& effect : enum_range<Aidl::Effect>()) {
584 for (const auto& strength : enum_range<Aidl::EffectStrength>()) {
585 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
586 }
587 }
588 }
589
590 protected:
591 auto getEffect(const State& state) const {
592 return static_cast<Aidl::Effect>(this->getOtherArg(state, 0));
593 }
594
595 auto getStrength(const State& state) const {
596 return static_cast<Aidl::EffectStrength>(this->getOtherArg(state, 1));
597 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000598
599 bool isEffectSupported(const Aidl::Effect& effect) {
600 std::vector<Aidl::Effect> supported;
601 mVibrator->getSupportedEffects(&supported);
602 return std::find(supported.begin(), supported.end(), effect) != supported.end();
603 }
604
605 bool isAlwaysOnEffectSupported(const Aidl::Effect& effect) {
606 std::vector<Aidl::Effect> supported;
607 mVibrator->getSupportedAlwaysOnEffects(&supported);
608 return std::find(supported.begin(), supported.end(), effect) != supported.end();
609 }
610};
611
612class SlowVibratorEffectsBench_Aidl : public VibratorEffectsBench_Aidl {
613 public:
614 static void DefaultConfig(Benchmark* b) {
615 VibratorEffectsBench_Aidl::DefaultConfig(b);
616 SlowBenchConfig(b);
617 }
Lais Andradee29acd82020-08-07 13:21:17 +0000618};
619
620BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000621 if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000622 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000623 return;
624 }
625
626 int32_t id = 1;
627 auto effect = getEffect(state);
628 auto strength = getStrength(state);
629
Lais Andrade59a5d542024-03-12 11:53:00 +0000630 if (!isAlwaysOnEffectSupported(effect)) {
631 state.SkipWithMessage("always on effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000632 return;
633 }
634
635 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000636 // Test
637 if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
638 return;
639 }
640
641 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000642 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000643 if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
644 return;
645 }
646 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000647 }
648});
649
650BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000651 if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000652 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000653 return;
654 }
655
656 int32_t id = 1;
657 auto effect = getEffect(state);
658 auto strength = getStrength(state);
659
Lais Andrade59a5d542024-03-12 11:53:00 +0000660 if (!isAlwaysOnEffectSupported(effect)) {
661 state.SkipWithMessage("always on effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000662 return;
663 }
664
665 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000666 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000667 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000668 if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
669 return;
670 }
Lais Andradee29acd82020-08-07 13:21:17 +0000671 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000672
673 // Test
674 if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
675 return;
676 }
Lais Andradee29acd82020-08-07 13:21:17 +0000677 }
678});
679
Lais Andrade59a5d542024-03-12 11:53:00 +0000680BENCHMARK_WRAPPER(SlowVibratorEffectsBench_Aidl, perform, {
Lais Andradee29acd82020-08-07 13:21:17 +0000681 auto effect = getEffect(state);
682 auto strength = getStrength(state);
Lais Andradee29acd82020-08-07 13:21:17 +0000683
Lais Andrade59a5d542024-03-12 11:53:00 +0000684 if (!isEffectSupported(effect)) {
685 state.SkipWithMessage("effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000686 return;
687 }
688
Lais Andrade59a5d542024-03-12 11:53:00 +0000689 int32_t lengthMs = 0;
690
Lais Andradee29acd82020-08-07 13:21:17 +0000691 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000692 auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback()
693 : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100694 // Grab the future before callback promise is destroyed by the HAL.
695 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000696
697 // Test
698 if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) {
699 return;
700 }
701
702 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000703 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000704 if (shouldSkipWithError(state, mVibrator->off())) {
705 return;
706 }
Lais Andradea5131c52024-06-12 16:39:29 +0100707 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000708 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000709 }
710});
711
712class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl {
713 public:
714 static void DefaultArgs(Benchmark* b) {
715 b->ArgNames({"Primitive"});
716 for (const auto& primitive : enum_range<Aidl::CompositePrimitive>()) {
717 b->Args({static_cast<long>(primitive)});
718 }
719 }
720
721 protected:
722 auto getPrimitive(const State& state) const {
723 return static_cast<Aidl::CompositePrimitive>(this->getOtherArg(state, 0));
724 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000725
726 bool isPrimitiveSupported(const Aidl::CompositePrimitive& primitive) {
727 std::vector<Aidl::CompositePrimitive> supported;
728 mVibrator->getSupportedPrimitives(&supported);
729 return std::find(supported.begin(), supported.end(), primitive) != supported.end();
730 }
731};
732
733class SlowVibratorPrimitivesBench_Aidl : public VibratorPrimitivesBench_Aidl {
734 public:
735 static void DefaultConfig(Benchmark* b) {
736 VibratorPrimitivesBench_Aidl::DefaultConfig(b);
737 SlowBenchConfig(b);
738 }
Lais Andradee29acd82020-08-07 13:21:17 +0000739};
740
741BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, {
742 int32_t ms = 0;
743
744 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000745 if (shouldSkipWithError(state, mVibrator->getCompositionDelayMax(&ms))) {
746 return;
747 }
Lais Andradee29acd82020-08-07 13:21:17 +0000748 }
749});
750
751BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, {
752 int32_t size = 0;
753
754 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000755 if (shouldSkipWithError(state, mVibrator->getCompositionSizeMax(&size))) {
756 return;
757 }
Lais Andradee29acd82020-08-07 13:21:17 +0000758 }
759});
760
761BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000762 if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
Adrian Roos77659422024-02-09 17:20:54 +0000763 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000764 return;
765 }
766
767 auto primitive = getPrimitive(state);
768 int32_t ms = 0;
769
Lais Andrade59a5d542024-03-12 11:53:00 +0000770 if (!isPrimitiveSupported(primitive)) {
771 state.SkipWithMessage("primitive unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000772 return;
773 }
774
775 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000776 if (shouldSkipWithError(state, mVibrator->getPrimitiveDuration(primitive, &ms))) {
777 return;
778 }
Lais Andradee29acd82020-08-07 13:21:17 +0000779 }
780});
781
Lais Andrade59a5d542024-03-12 11:53:00 +0000782BENCHMARK_WRAPPER(SlowVibratorPrimitivesBench_Aidl, compose, {
783 if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
Adrian Roos77659422024-02-09 17:20:54 +0000784 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000785 return;
786 }
787
788 Aidl::CompositeEffect effect;
789 effect.primitive = getPrimitive(state);
790 effect.scale = 1.0f;
791 effect.delayMs = 0;
792
Lais Andrade59a5d542024-03-12 11:53:00 +0000793 if (effect.primitive == Aidl::CompositePrimitive::NOOP) {
794 state.SkipWithMessage("skipping primitive NOOP");
795 return;
796 }
797 if (!isPrimitiveSupported(effect.primitive)) {
798 state.SkipWithMessage("primitive unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000799 return;
800 }
801
Lais Andradee29acd82020-08-07 13:21:17 +0000802 std::vector<Aidl::CompositeEffect> effects;
803 effects.push_back(effect);
804
805 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000806 auto cb = new HalCallback();
Lais Andradea5131c52024-06-12 16:39:29 +0100807 // Grab the future before callback promise is moved and destroyed by the HAL.
808 auto cbFuture = cb->getFuture();
Lais Andrade59a5d542024-03-12 11:53:00 +0000809
810 // Test
811 if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) {
812 return;
813 }
814
815 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000816 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000817 if (shouldSkipWithError(state, mVibrator->off())) {
818 return;
819 }
Lais Andradea5131c52024-06-12 16:39:29 +0100820 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000821 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000822 }
823});
824
825BENCHMARK_MAIN();