blob: 8fe9cf7a5435ba4fc0ded86f623d7862d7e2da98 [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
Lais Andrade28c81f12024-06-24 14:32:22 +010019#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
20#include <aidl/android/hardware/vibrator/IVibrator.h>
21
22#include <android/binder_manager.h>
23#include <android/binder_process.h>
Lais Andradee29acd82020-08-07 13:21:17 +000024#include <android/hardware/vibrator/1.3/IVibrator.h>
Lais Andrade59a5d542024-03-12 11:53:00 +000025#include <future>
Lais Andradee29acd82020-08-07 13:21:17 +000026
Lais Andradee29acd82020-08-07 13:21:17 +000027using ::android::hardware::hidl_enum_range;
28using ::android::hardware::Return;
29using ::android::hardware::details::hidl_enum_values;
30using ::benchmark::Counter;
31using ::benchmark::Fixture;
32using ::benchmark::kMicrosecond;
33using ::benchmark::State;
34using ::benchmark::internal::Benchmark;
Lais Andrade28c81f12024-06-24 14:32:22 +010035using ::ndk::enum_range;
Lais Andrade59a5d542024-03-12 11:53:00 +000036
37using namespace ::std::chrono_literals;
Lais Andradee29acd82020-08-07 13:21:17 +000038
Lais Andrade28c81f12024-06-24 14:32:22 +010039namespace Aidl = ::aidl::android::hardware::vibrator;
Lais Andradee29acd82020-08-07 13:21:17 +000040namespace 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 {
Lais Andrade28c81f12024-06-24 14:32:22 +010059 ABinderProcess_setThreadPoolMaxThreadCount(1);
60 ABinderProcess_startThreadPool();
Lais Andrade59a5d542024-03-12 11:53:00 +000061 }
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:
Lais Andrade28c81f12024-06-24 14:32:22 +010078 std::shared_ptr<I> mVibrator;
Lais Andradee29acd82020-08-07 13:21:17 +000079};
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);
Lais Andrade28c81f12024-06-24 14:32:22 +010086 auto service = I::getService();
87 if (service) {
88 this->mVibrator = std::shared_ptr<I>(service.release());
89 } else {
90 this->mVibrator = nullptr;
91 }
Lais Andrade59a5d542024-03-12 11:53:00 +000092 }
93
94 protected:
95 bool shouldSkipWithError(State& state, const android::hardware::Return<V1_0::Status>&& ret) {
96 if (!ret.isOk()) {
97 state.SkipWithError(ret.description());
98 return true;
99 }
100 return false;
101 }
Lais Andradee29acd82020-08-07 13:21:17 +0000102};
103
104enum class EmptyEnum : uint32_t;
105template <>
106inline constexpr std::array<EmptyEnum, 0> hidl_enum_values<EmptyEnum> = {};
107
108template <typename T, typename U>
109std::set<T> difference(const hidl_enum_range<T>& t, const hidl_enum_range<U>& u) {
110 class Compare {
111 public:
112 bool operator()(const T& a, const U& b) { return a < static_cast<T>(b); }
113 bool operator()(const U& a, const T& b) { return static_cast<T>(a) < b; }
114 };
115 std::set<T> ret;
116
117 std::set_difference(t.begin(), t.end(), u.begin(), u.end(),
118 std::insert_iterator<decltype(ret)>(ret, ret.begin()), Compare());
119
120 return ret;
121}
122
123template <typename I, typename E1, typename E2 = EmptyEnum>
124class VibratorEffectsBench : public VibratorBench<I> {
125 public:
126 using Effect = E1;
127 using EffectStrength = V1_0::EffectStrength;
128 using Status = V1_0::Status;
129
130 public:
131 static void DefaultArgs(Benchmark* b) {
132 b->ArgNames({"Effect", "Strength"});
133 for (const auto& effect : difference(hidl_enum_range<E1>(), hidl_enum_range<E2>())) {
134 for (const auto& strength : hidl_enum_range<EffectStrength>()) {
135 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
136 }
137 }
138 }
139
140 void performBench(State* state, Return<void> (I::*performApi)(Effect, EffectStrength,
141 typename I::perform_cb)) {
142 auto effect = getEffect(*state);
143 auto strength = getStrength(*state);
144 bool supported = true;
145
146 (*this->mVibrator.*performApi)(effect, strength, [&](Status status, uint32_t /*lengthMs*/) {
147 if (status == Status::UNSUPPORTED_OPERATION) {
148 supported = false;
149 }
150 });
151
152 if (!supported) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000153 state->SkipWithMessage("effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000154 return;
155 }
156
157 for (auto _ : *state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000158 // Test
159 auto ret = (*this->mVibrator.*performApi)(
160 effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {});
161
162 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000163 state->PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000164 if (!ret.isOk()) {
165 state->SkipWithError(ret.description());
166 return;
167 }
168 if (this->shouldSkipWithError(*state, this->mVibrator->off())) {
169 return;
170 }
171 state->ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000172 }
173 }
174
175 protected:
176 auto getEffect(const State& state) const {
177 return static_cast<Effect>(this->getOtherArg(state, 0));
178 }
179
180 auto getStrength(const State& state) const {
181 return static_cast<EffectStrength>(this->getOtherArg(state, 1));
182 }
183};
184
Adrian Roos77659422024-02-09 17:20:54 +0000185#define BENCHMARK_WRAPPER(fixt, test, code) \
186 BENCHMARK_DEFINE_F(fixt, test) \
187 /* NOLINTNEXTLINE */ \
188 (State & state) { \
189 if (!mVibrator) { \
190 state.SkipWithMessage("HAL unavailable"); \
191 return; \
192 } \
193 \
194 code \
195 } \
Lais Andradee29acd82020-08-07 13:21:17 +0000196 BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs)
197
198using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>;
199
200BENCHMARK_WRAPPER(VibratorBench_V1_0, on, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000201 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000202
203 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000204 // Test
205 if (shouldSkipWithError(state, mVibrator->on(ms))) {
206 return;
207 }
208
209 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000210 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000211 if (shouldSkipWithError(state, mVibrator->off())) {
212 return;
213 }
214 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000215 }
216});
217
218BENCHMARK_WRAPPER(VibratorBench_V1_0, off, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000219 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000220
221 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000222 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000223 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000224 if (shouldSkipWithError(state, mVibrator->on(ms))) {
225 return;
226 }
Lais Andradee29acd82020-08-07 13:21:17 +0000227 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000228
229 // Test
230 if (shouldSkipWithError(state, mVibrator->off())) {
231 return;
232 }
Lais Andradee29acd82020-08-07 13:21:17 +0000233 }
234});
235
236BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, {
237 for (auto _ : state) {
238 mVibrator->supportsAmplitudeControl();
239 }
240});
241
242BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000243 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000244 uint8_t amplitude = UINT8_MAX;
245
246 if (!mVibrator->supportsAmplitudeControl()) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000247 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000248 return;
249 }
250
Lais Andrade59a5d542024-03-12 11:53:00 +0000251 if (shouldSkipWithError(state, mVibrator->on(ms))) {
252 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000253 }
254
Lais Andrade59a5d542024-03-12 11:53:00 +0000255 for (auto _ : state) {
256 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
257 return;
258 }
259 }
Lais Andradee29acd82020-08-07 13:21:17 +0000260});
261
262using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>;
263
264BENCHMARK_WRAPPER(VibratorEffectsBench_V1_0, perform,
265 { performBench(&state, &V1_0::IVibrator::perform); });
266
267using VibratorEffectsBench_V1_1 =
268 VibratorEffectsBench<V1_1::IVibrator, V1_1::Effect_1_1, V1_0::Effect>;
269
270BENCHMARK_WRAPPER(VibratorEffectsBench_V1_1, perform_1_1,
271 { performBench(&state, &V1_1::IVibrator::perform_1_1); });
272
273using VibratorEffectsBench_V1_2 =
274 VibratorEffectsBench<V1_2::IVibrator, V1_2::Effect, V1_1::Effect_1_1>;
275
276BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2,
277 { performBench(&state, &V1_2::IVibrator::perform_1_2); });
278
Lais Andrade59a5d542024-03-12 11:53:00 +0000279class VibratorBench_V1_3 : public VibratorBench<V1_3::IVibrator> {
280 public:
281 void TearDown(State& state) override {
282 VibratorBench::TearDown(state);
283 if (mVibrator) {
284 mVibrator->setExternalControl(false);
285 }
286 }
287};
Lais Andradee29acd82020-08-07 13:21:17 +0000288
289BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, {
290 for (auto _ : state) {
291 mVibrator->supportsExternalControl();
292 }
293});
294
295BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, {
Lais Andradee29acd82020-08-07 13:21:17 +0000296 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000297 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000298 return;
299 }
300
301 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000302 // Test
303 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
304 return;
305 }
306
307 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000308 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000309 if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
310 return;
311 }
312 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000313 }
314});
315
316BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, {
317 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000318 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000319 return;
320 }
321
Lais Andrade59a5d542024-03-12 11:53:00 +0000322 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
323 return;
324 }
Lais Andradee29acd82020-08-07 13:21:17 +0000325
326 for (auto _ : state) {
327 mVibrator->supportsAmplitudeControl();
328 }
Lais Andradee29acd82020-08-07 13:21:17 +0000329});
330
331BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, {
332 uint8_t amplitude = UINT8_MAX;
333
334 if (!mVibrator->supportsExternalControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000335 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000336 return;
337 }
338
Lais Andrade59a5d542024-03-12 11:53:00 +0000339 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
340 return;
341 }
Lais Andradee29acd82020-08-07 13:21:17 +0000342
343 if (!mVibrator->supportsAmplitudeControl()) {
Adrian Roos77659422024-02-09 17:20:54 +0000344 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000345 return;
346 }
347
348 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000349 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
350 return;
351 }
Lais Andradee29acd82020-08-07 13:21:17 +0000352 }
Lais Andradee29acd82020-08-07 13:21:17 +0000353});
354
355using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>;
356
357BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3,
358 { performBench(&state, &V1_3::IVibrator::perform_1_3); });
359
360class VibratorBench_Aidl : public BaseBench<Aidl::IVibrator> {
361 public:
Lais Andrade59a5d542024-03-12 11:53:00 +0000362 void SetUp(State& state) override {
363 BaseBench::SetUp(state);
Lais Andrade28c81f12024-06-24 14:32:22 +0100364 auto serviceName = std::string(Aidl::IVibrator::descriptor) + "/default";
365 this->mVibrator = Aidl::IVibrator::fromBinder(
366 ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
Lais Andradee29acd82020-08-07 13:21:17 +0000367 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000368
369 void TearDown(State& state) override {
370 BaseBench::TearDown(state);
371 if (mVibrator) {
372 mVibrator->setExternalControl(false);
373 }
374 }
375
376 protected:
377 int32_t hasCapabilities(int32_t capabilities) {
378 int32_t deviceCapabilities = 0;
379 this->mVibrator->getCapabilities(&deviceCapabilities);
380 return (deviceCapabilities & capabilities) == capabilities;
381 }
382
Lais Andrade28c81f12024-06-24 14:32:22 +0100383 bool shouldSkipWithError(State& state, const ndk::ScopedAStatus&& status) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000384 if (!status.isOk()) {
Lais Andrade28c81f12024-06-24 14:32:22 +0100385 state.SkipWithError(status.getMessage());
Lais Andrade59a5d542024-03-12 11:53:00 +0000386 return true;
387 }
388 return false;
389 }
390
Lais Andradea5131c52024-06-12 16:39:29 +0100391 void waitForComplete(std::future<void>& callbackFuture) {
392 // Wait until the HAL has finished processing previous vibration before starting a new one,
393 // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
394 // HAL implementations are waiting on previous vibration cleanup and might be significantly
395 // slower, so make sure we measure vibrations on a clean slate.
396 if (callbackFuture.valid()) {
397 callbackFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT);
398 }
399 }
400
Lais Andrade59a5d542024-03-12 11:53:00 +0000401 static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); }
402};
403
404class SlowVibratorBench_Aidl : public VibratorBench_Aidl {
405 public:
406 static void DefaultConfig(Benchmark* b) {
407 VibratorBench_Aidl::DefaultConfig(b);
408 SlowBenchConfig(b);
409 }
Lais Andradee29acd82020-08-07 13:21:17 +0000410};
411
412class HalCallback : public Aidl::BnVibratorCallback {
413 public:
414 HalCallback() = default;
415 ~HalCallback() = default;
416
Lais Andrade28c81f12024-06-24 14:32:22 +0100417 ndk::ScopedAStatus onComplete() override {
Lais Andrade59a5d542024-03-12 11:53:00 +0000418 mPromise.set_value();
Lais Andrade28c81f12024-06-24 14:32:22 +0100419 return ndk::ScopedAStatus::ok();
Lais Andrade59a5d542024-03-12 11:53:00 +0000420 }
421
Lais Andradea5131c52024-06-12 16:39:29 +0100422 std::future<void> getFuture() { return mPromise.get_future(); }
Lais Andrade59a5d542024-03-12 11:53:00 +0000423
424 private:
425 std::promise<void> mPromise;
Lais Andradee29acd82020-08-07 13:21:17 +0000426};
427
Lais Andrade59a5d542024-03-12 11:53:00 +0000428BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, on, {
429 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000430
431 for (auto _ : state) {
Lais Andrade28c81f12024-06-24 14:32:22 +0100432 auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
433 ? ndk::SharedRefBase::make<HalCallback>()
434 : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100435 // Grab the future before callback promise is destroyed by the HAL.
436 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000437
438 // Test
439 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
440 return;
441 }
442
443 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000444 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000445 if (shouldSkipWithError(state, mVibrator->off())) {
446 return;
447 }
Lais Andradea5131c52024-06-12 16:39:29 +0100448 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000449 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000450 }
451});
452
Lais Andrade59a5d542024-03-12 11:53:00 +0000453BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, off, {
454 auto ms = MAX_ON_DURATION_MS;
455
Lais Andradee29acd82020-08-07 13:21:17 +0000456 for (auto _ : state) {
Lais Andrade28c81f12024-06-24 14:32:22 +0100457 auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
458 ? ndk::SharedRefBase::make<HalCallback>()
459 : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100460 // Grab the future before callback promise is destroyed by the HAL.
461 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000462
463 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000464 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000465 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
466 return;
467 }
Lais Andradee29acd82020-08-07 13:21:17 +0000468 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000469
470 // Test
471 if (shouldSkipWithError(state, mVibrator->off())) {
472 return;
473 }
474
475 // Cleanup
476 state.PauseTiming();
Lais Andradea5131c52024-06-12 16:39:29 +0100477 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000478 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000479 }
480});
481
482BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, {
483 int32_t capabilities = 0;
484
485 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000486 if (shouldSkipWithError(state, mVibrator->getCapabilities(&capabilities))) {
487 return;
488 }
Lais Andradee29acd82020-08-07 13:21:17 +0000489 }
490});
491
492BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000493 auto ms = MAX_ON_DURATION_MS;
494 float amplitude = 1.0f;
495
496 if (!hasCapabilities(Aidl::IVibrator::CAP_AMPLITUDE_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000497 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000498 return;
499 }
500
Lais Andrade28c81f12024-06-24 14:32:22 +0100501 auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
502 ? ndk::SharedRefBase::make<HalCallback>()
503 : nullptr;
Lais Andrade59a5d542024-03-12 11:53:00 +0000504 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
505 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000506 }
507
Lais Andrade59a5d542024-03-12 11:53:00 +0000508 for (auto _ : state) {
509 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
510 return;
511 }
512 }
Lais Andradee29acd82020-08-07 13:21:17 +0000513});
514
515BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000516 if (!hasCapabilities(Aidl::IVibrator::CAP_EXTERNAL_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000517 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000518 return;
519 }
520
521 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000522 // Test
523 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
524 return;
525 }
526
527 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000528 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000529 if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
530 return;
531 }
532 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000533 }
534});
535
536BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000537 auto externalControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_CONTROL);
538 auto externalAmplitudeControl =
539 static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL);
540 if (!hasCapabilities(externalControl | externalAmplitudeControl)) {
Adrian Roos77659422024-02-09 17:20:54 +0000541 state.SkipWithMessage("external amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000542 return;
543 }
544
Lais Andrade59a5d542024-03-12 11:53:00 +0000545 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
546 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000547 }
548
Lais Andrade59a5d542024-03-12 11:53:00 +0000549 float amplitude = 1.0f;
550 for (auto _ : state) {
551 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
552 return;
553 }
554 }
Lais Andradee29acd82020-08-07 13:21:17 +0000555});
556
557BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, {
558 std::vector<Aidl::Effect> supportedEffects;
559
560 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000561 if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) {
562 return;
563 }
Lais Andradee29acd82020-08-07 13:21:17 +0000564 }
565});
566
567BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000568 if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
569 state.SkipWithMessage("always on control unavailable");
570 return;
571 }
572
Lais Andradee29acd82020-08-07 13:21:17 +0000573 std::vector<Aidl::Effect> supportedEffects;
574
575 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000576 if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) {
577 return;
578 }
Lais Andradee29acd82020-08-07 13:21:17 +0000579 }
580});
581
582BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, {
583 std::vector<Aidl::CompositePrimitive> supportedPrimitives;
584
585 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000586 if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) {
587 return;
588 }
Lais Andradee29acd82020-08-07 13:21:17 +0000589 }
590});
591
592class VibratorEffectsBench_Aidl : public VibratorBench_Aidl {
593 public:
594 static void DefaultArgs(Benchmark* b) {
595 b->ArgNames({"Effect", "Strength"});
596 for (const auto& effect : enum_range<Aidl::Effect>()) {
597 for (const auto& strength : enum_range<Aidl::EffectStrength>()) {
598 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
599 }
600 }
601 }
602
603 protected:
604 auto getEffect(const State& state) const {
605 return static_cast<Aidl::Effect>(this->getOtherArg(state, 0));
606 }
607
608 auto getStrength(const State& state) const {
609 return static_cast<Aidl::EffectStrength>(this->getOtherArg(state, 1));
610 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000611
612 bool isEffectSupported(const Aidl::Effect& effect) {
613 std::vector<Aidl::Effect> supported;
614 mVibrator->getSupportedEffects(&supported);
615 return std::find(supported.begin(), supported.end(), effect) != supported.end();
616 }
617
618 bool isAlwaysOnEffectSupported(const Aidl::Effect& effect) {
619 std::vector<Aidl::Effect> supported;
620 mVibrator->getSupportedAlwaysOnEffects(&supported);
621 return std::find(supported.begin(), supported.end(), effect) != supported.end();
622 }
623};
624
625class SlowVibratorEffectsBench_Aidl : public VibratorEffectsBench_Aidl {
626 public:
627 static void DefaultConfig(Benchmark* b) {
628 VibratorEffectsBench_Aidl::DefaultConfig(b);
629 SlowBenchConfig(b);
630 }
Lais Andradee29acd82020-08-07 13:21:17 +0000631};
632
633BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000634 if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000635 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000636 return;
637 }
638
639 int32_t id = 1;
640 auto effect = getEffect(state);
641 auto strength = getStrength(state);
642
Lais Andrade59a5d542024-03-12 11:53:00 +0000643 if (!isAlwaysOnEffectSupported(effect)) {
644 state.SkipWithMessage("always on effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000645 return;
646 }
647
648 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000649 // Test
650 if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
651 return;
652 }
653
654 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000655 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000656 if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
657 return;
658 }
659 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000660 }
661});
662
663BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000664 if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000665 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000666 return;
667 }
668
669 int32_t id = 1;
670 auto effect = getEffect(state);
671 auto strength = getStrength(state);
672
Lais Andrade59a5d542024-03-12 11:53:00 +0000673 if (!isAlwaysOnEffectSupported(effect)) {
674 state.SkipWithMessage("always on effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000675 return;
676 }
677
678 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000679 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000680 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000681 if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
682 return;
683 }
Lais Andradee29acd82020-08-07 13:21:17 +0000684 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000685
686 // Test
687 if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
688 return;
689 }
Lais Andradee29acd82020-08-07 13:21:17 +0000690 }
691});
692
Lais Andrade59a5d542024-03-12 11:53:00 +0000693BENCHMARK_WRAPPER(SlowVibratorEffectsBench_Aidl, perform, {
Lais Andradee29acd82020-08-07 13:21:17 +0000694 auto effect = getEffect(state);
695 auto strength = getStrength(state);
Lais Andradee29acd82020-08-07 13:21:17 +0000696
Lais Andrade59a5d542024-03-12 11:53:00 +0000697 if (!isEffectSupported(effect)) {
698 state.SkipWithMessage("effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000699 return;
700 }
701
Lais Andrade59a5d542024-03-12 11:53:00 +0000702 int32_t lengthMs = 0;
703
Lais Andradee29acd82020-08-07 13:21:17 +0000704 for (auto _ : state) {
Lais Andrade28c81f12024-06-24 14:32:22 +0100705 auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK)
706 ? ndk::SharedRefBase::make<HalCallback>()
707 : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100708 // Grab the future before callback promise is destroyed by the HAL.
709 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000710
711 // Test
712 if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) {
713 return;
714 }
715
716 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000717 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000718 if (shouldSkipWithError(state, mVibrator->off())) {
719 return;
720 }
Lais Andradea5131c52024-06-12 16:39:29 +0100721 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000722 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000723 }
724});
725
726class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl {
727 public:
728 static void DefaultArgs(Benchmark* b) {
729 b->ArgNames({"Primitive"});
730 for (const auto& primitive : enum_range<Aidl::CompositePrimitive>()) {
731 b->Args({static_cast<long>(primitive)});
732 }
733 }
734
735 protected:
736 auto getPrimitive(const State& state) const {
737 return static_cast<Aidl::CompositePrimitive>(this->getOtherArg(state, 0));
738 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000739
740 bool isPrimitiveSupported(const Aidl::CompositePrimitive& primitive) {
741 std::vector<Aidl::CompositePrimitive> supported;
742 mVibrator->getSupportedPrimitives(&supported);
743 return std::find(supported.begin(), supported.end(), primitive) != supported.end();
744 }
745};
746
747class SlowVibratorPrimitivesBench_Aidl : public VibratorPrimitivesBench_Aidl {
748 public:
749 static void DefaultConfig(Benchmark* b) {
750 VibratorPrimitivesBench_Aidl::DefaultConfig(b);
751 SlowBenchConfig(b);
752 }
Lais Andradee29acd82020-08-07 13:21:17 +0000753};
754
755BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, {
756 int32_t ms = 0;
757
758 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000759 if (shouldSkipWithError(state, mVibrator->getCompositionDelayMax(&ms))) {
760 return;
761 }
Lais Andradee29acd82020-08-07 13:21:17 +0000762 }
763});
764
765BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, {
766 int32_t size = 0;
767
768 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000769 if (shouldSkipWithError(state, mVibrator->getCompositionSizeMax(&size))) {
770 return;
771 }
Lais Andradee29acd82020-08-07 13:21:17 +0000772 }
773});
774
775BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000776 if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
Adrian Roos77659422024-02-09 17:20:54 +0000777 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000778 return;
779 }
780
781 auto primitive = getPrimitive(state);
782 int32_t ms = 0;
783
Lais Andrade59a5d542024-03-12 11:53:00 +0000784 if (!isPrimitiveSupported(primitive)) {
785 state.SkipWithMessage("primitive unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000786 return;
787 }
788
789 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000790 if (shouldSkipWithError(state, mVibrator->getPrimitiveDuration(primitive, &ms))) {
791 return;
792 }
Lais Andradee29acd82020-08-07 13:21:17 +0000793 }
794});
795
Lais Andrade59a5d542024-03-12 11:53:00 +0000796BENCHMARK_WRAPPER(SlowVibratorPrimitivesBench_Aidl, compose, {
797 if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) {
Adrian Roos77659422024-02-09 17:20:54 +0000798 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000799 return;
800 }
801
802 Aidl::CompositeEffect effect;
803 effect.primitive = getPrimitive(state);
804 effect.scale = 1.0f;
805 effect.delayMs = 0;
806
Lais Andrade59a5d542024-03-12 11:53:00 +0000807 if (effect.primitive == Aidl::CompositePrimitive::NOOP) {
808 state.SkipWithMessage("skipping primitive NOOP");
809 return;
810 }
811 if (!isPrimitiveSupported(effect.primitive)) {
812 state.SkipWithMessage("primitive unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000813 return;
814 }
815
Lais Andradee29acd82020-08-07 13:21:17 +0000816 std::vector<Aidl::CompositeEffect> effects;
817 effects.push_back(effect);
818
819 for (auto _ : state) {
Lais Andrade28c81f12024-06-24 14:32:22 +0100820 auto cb = ndk::SharedRefBase::make<HalCallback>();
Lais Andradea5131c52024-06-12 16:39:29 +0100821 // Grab the future before callback promise is moved and destroyed by the HAL.
822 auto cbFuture = cb->getFuture();
Lais Andrade59a5d542024-03-12 11:53:00 +0000823
824 // Test
825 if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) {
826 return;
827 }
828
829 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000830 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000831 if (shouldSkipWithError(state, mVibrator->off())) {
832 return;
833 }
Lais Andradea5131c52024-06-12 16:39:29 +0100834 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000835 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000836 }
837});
838
839BENCHMARK_MAIN();