blob: 76d67ef0c9410f0deed8c5c58868add207ea6c77 [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 Andrade59a5d542024-03-12 11:53:00 +000024#include <future>
Lais Andradee29acd82020-08-07 13:21:17 +000025
Lais Andradee29acd82020-08-07 13:21:17 +000026using ::benchmark::Counter;
27using ::benchmark::Fixture;
28using ::benchmark::kMicrosecond;
29using ::benchmark::State;
30using ::benchmark::internal::Benchmark;
Lais Andrade28c81f12024-06-24 14:32:22 +010031using ::ndk::enum_range;
Lais Andrade59a5d542024-03-12 11:53:00 +000032
Lais Andrade6677c6f2025-03-21 09:48:28 -070033using namespace ::aidl::android::hardware::vibrator;
Lais Andrade59a5d542024-03-12 11:53:00 +000034using namespace ::std::chrono_literals;
Lais Andradee29acd82020-08-07 13:21:17 +000035
Lais Andrade59a5d542024-03-12 11:53:00 +000036// Fixed number of iterations for benchmarks that trigger a vibration on the loop.
37// They require slow cleanup to ensure a stable state on each run and less noisy metrics.
38static constexpr auto VIBRATION_ITERATIONS = 500;
39
40// Timeout to wait for vibration callback completion.
41static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms;
42
43// Max duration the vibrator can be turned on, in milliseconds.
44static constexpr uint32_t MAX_ON_DURATION_MS = UINT16_MAX;
45
Lais Andrade6677c6f2025-03-21 09:48:28 -070046class VibratorBench : public Fixture {
Lais Andradee29acd82020-08-07 13:21:17 +000047 public:
Lais Andrade59a5d542024-03-12 11:53:00 +000048 void SetUp(State& /*state*/) override {
Lais Andrade28c81f12024-06-24 14:32:22 +010049 ABinderProcess_setThreadPoolMaxThreadCount(1);
50 ABinderProcess_startThreadPool();
Lais Andrade6677c6f2025-03-21 09:48:28 -070051 auto serviceName = std::string(IVibrator::descriptor) + "/default";
52 this->mVibrator = IVibrator::fromBinder(
53 ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
Lais Andrade59a5d542024-03-12 11:53:00 +000054 }
55
Lais Andradee29acd82020-08-07 13:21:17 +000056 void TearDown(State& /*state*/) override {
Lais Andrade59a5d542024-03-12 11:53:00 +000057 if (mVibrator) {
58 mVibrator->off();
Lais Andrade6677c6f2025-03-21 09:48:28 -070059 mVibrator->setExternalControl(false);
Lais Andradee29acd82020-08-07 13:21:17 +000060 }
Lais Andradee29acd82020-08-07 13:21:17 +000061 }
62
63 static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
64
Lais Andrade6677c6f2025-03-21 09:48:28 -070065 static void DefaultArgs(Benchmark* /*b*/) { /* none */ }
Lais Andradee29acd82020-08-07 13:21:17 +000066
67 protected:
Lais Andrade6677c6f2025-03-21 09:48:28 -070068 std::shared_ptr<IVibrator> mVibrator;
69
Lais Andradee29acd82020-08-07 13:21:17 +000070 auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
71
Lais Andrade59a5d542024-03-12 11:53:00 +000072 int32_t hasCapabilities(int32_t capabilities) {
73 int32_t deviceCapabilities = 0;
74 this->mVibrator->getCapabilities(&deviceCapabilities);
75 return (deviceCapabilities & capabilities) == capabilities;
76 }
77
Lais Andrade28c81f12024-06-24 14:32:22 +010078 bool shouldSkipWithError(State& state, const ndk::ScopedAStatus&& status) {
Lais Andrade59a5d542024-03-12 11:53:00 +000079 if (!status.isOk()) {
Lais Andrade28c81f12024-06-24 14:32:22 +010080 state.SkipWithError(status.getMessage());
Lais Andrade59a5d542024-03-12 11:53:00 +000081 return true;
82 }
83 return false;
84 }
85
Lais Andradea5131c52024-06-12 16:39:29 +010086 void waitForComplete(std::future<void>& callbackFuture) {
87 // Wait until the HAL has finished processing previous vibration before starting a new one,
88 // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
89 // HAL implementations are waiting on previous vibration cleanup and might be significantly
90 // slower, so make sure we measure vibrations on a clean slate.
91 if (callbackFuture.valid()) {
92 callbackFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT);
93 }
94 }
95
Lais Andrade59a5d542024-03-12 11:53:00 +000096 static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); }
97};
98
Lais Andrade6677c6f2025-03-21 09:48:28 -070099class SlowVibratorBench : public VibratorBench {
Lais Andrade59a5d542024-03-12 11:53:00 +0000100 public:
101 static void DefaultConfig(Benchmark* b) {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700102 VibratorBench::DefaultConfig(b);
Lais Andrade59a5d542024-03-12 11:53:00 +0000103 SlowBenchConfig(b);
104 }
Lais Andradee29acd82020-08-07 13:21:17 +0000105};
106
Lais Andrade6677c6f2025-03-21 09:48:28 -0700107class HalCallback : public BnVibratorCallback {
Lais Andradee29acd82020-08-07 13:21:17 +0000108 public:
109 HalCallback() = default;
110 ~HalCallback() = default;
111
Lais Andrade28c81f12024-06-24 14:32:22 +0100112 ndk::ScopedAStatus onComplete() override {
Lais Andrade59a5d542024-03-12 11:53:00 +0000113 mPromise.set_value();
Lais Andrade28c81f12024-06-24 14:32:22 +0100114 return ndk::ScopedAStatus::ok();
Lais Andrade59a5d542024-03-12 11:53:00 +0000115 }
116
Lais Andradea5131c52024-06-12 16:39:29 +0100117 std::future<void> getFuture() { return mPromise.get_future(); }
Lais Andrade59a5d542024-03-12 11:53:00 +0000118
119 private:
120 std::promise<void> mPromise;
Lais Andradee29acd82020-08-07 13:21:17 +0000121};
122
Lais Andrade6677c6f2025-03-21 09:48:28 -0700123#define BENCHMARK_WRAPPER(fixt, test, code) \
124 BENCHMARK_DEFINE_F(fixt, test) \
125 /* NOLINTNEXTLINE */ \
126 (State & state) { \
127 if (!mVibrator) { \
128 state.SkipWithMessage("HAL unavailable"); \
129 return; \
130 } \
131 \
132 code \
133 } \
134 BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultConfig)->Apply(fixt::DefaultArgs)
135
136BENCHMARK_WRAPPER(SlowVibratorBench, on, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000137 auto ms = MAX_ON_DURATION_MS;
Lais Andradee29acd82020-08-07 13:21:17 +0000138
139 for (auto _ : state) {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700140 auto cb = hasCapabilities(IVibrator::CAP_ON_CALLBACK)
Lais Andrade28c81f12024-06-24 14:32:22 +0100141 ? ndk::SharedRefBase::make<HalCallback>()
142 : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100143 // Grab the future before callback promise is destroyed by the HAL.
144 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000145
146 // Test
147 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
148 return;
149 }
150
151 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000152 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000153 if (shouldSkipWithError(state, mVibrator->off())) {
154 return;
155 }
Lais Andradea5131c52024-06-12 16:39:29 +0100156 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000157 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000158 }
159});
160
Lais Andrade6677c6f2025-03-21 09:48:28 -0700161BENCHMARK_WRAPPER(SlowVibratorBench, off, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000162 auto ms = MAX_ON_DURATION_MS;
163
Lais Andradee29acd82020-08-07 13:21:17 +0000164 for (auto _ : state) {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700165 auto cb = hasCapabilities(IVibrator::CAP_ON_CALLBACK)
Lais Andrade28c81f12024-06-24 14:32:22 +0100166 ? ndk::SharedRefBase::make<HalCallback>()
167 : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100168 // Grab the future before callback promise is destroyed by the HAL.
169 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000170
171 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000172 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000173 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
174 return;
175 }
Lais Andradee29acd82020-08-07 13:21:17 +0000176 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000177
178 // Test
179 if (shouldSkipWithError(state, mVibrator->off())) {
180 return;
181 }
182
183 // Cleanup
184 state.PauseTiming();
Lais Andradea5131c52024-06-12 16:39:29 +0100185 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000186 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000187 }
188});
189
Lais Andrade6677c6f2025-03-21 09:48:28 -0700190BENCHMARK_WRAPPER(VibratorBench, getCapabilities, {
Lais Andradee29acd82020-08-07 13:21:17 +0000191 int32_t capabilities = 0;
192
193 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000194 if (shouldSkipWithError(state, mVibrator->getCapabilities(&capabilities))) {
195 return;
196 }
Lais Andradee29acd82020-08-07 13:21:17 +0000197 }
198});
199
Lais Andrade6677c6f2025-03-21 09:48:28 -0700200BENCHMARK_WRAPPER(VibratorBench, setAmplitude, {
Lais Andrade59a5d542024-03-12 11:53:00 +0000201 auto ms = MAX_ON_DURATION_MS;
202 float amplitude = 1.0f;
203
Lais Andrade6677c6f2025-03-21 09:48:28 -0700204 if (!hasCapabilities(IVibrator::CAP_AMPLITUDE_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000205 state.SkipWithMessage("amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000206 return;
207 }
208
Lais Andrade6677c6f2025-03-21 09:48:28 -0700209 auto cb = hasCapabilities(IVibrator::CAP_ON_CALLBACK)
Lais Andrade28c81f12024-06-24 14:32:22 +0100210 ? ndk::SharedRefBase::make<HalCallback>()
211 : nullptr;
Lais Andrade59a5d542024-03-12 11:53:00 +0000212 if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
213 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000214 }
215
Lais Andrade59a5d542024-03-12 11:53:00 +0000216 for (auto _ : state) {
217 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
218 return;
219 }
220 }
Lais Andradee29acd82020-08-07 13:21:17 +0000221});
222
Lais Andrade6677c6f2025-03-21 09:48:28 -0700223BENCHMARK_WRAPPER(VibratorBench, setExternalControl, {
224 if (!hasCapabilities(IVibrator::CAP_EXTERNAL_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000225 state.SkipWithMessage("external control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000226 return;
227 }
228
229 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000230 // Test
231 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
232 return;
233 }
234
235 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000236 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000237 if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) {
238 return;
239 }
240 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000241 }
242});
243
Lais Andrade6677c6f2025-03-21 09:48:28 -0700244BENCHMARK_WRAPPER(VibratorBench, setExternalAmplitude, {
245 auto externalControl = static_cast<int32_t>(IVibrator::CAP_EXTERNAL_CONTROL);
Lais Andrade59a5d542024-03-12 11:53:00 +0000246 auto externalAmplitudeControl =
Lais Andrade6677c6f2025-03-21 09:48:28 -0700247 static_cast<int32_t>(IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL);
Lais Andrade59a5d542024-03-12 11:53:00 +0000248 if (!hasCapabilities(externalControl | externalAmplitudeControl)) {
Adrian Roos77659422024-02-09 17:20:54 +0000249 state.SkipWithMessage("external amplitude control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000250 return;
251 }
252
Lais Andrade59a5d542024-03-12 11:53:00 +0000253 if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
254 return;
Lais Andradee29acd82020-08-07 13:21:17 +0000255 }
256
Lais Andrade59a5d542024-03-12 11:53:00 +0000257 float amplitude = 1.0f;
258 for (auto _ : state) {
259 if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
260 return;
261 }
262 }
Lais Andradee29acd82020-08-07 13:21:17 +0000263});
264
Lais Andrade6677c6f2025-03-21 09:48:28 -0700265BENCHMARK_WRAPPER(VibratorBench, getSupportedEffects, {
266 std::vector<Effect> supportedEffects;
Lais Andradee29acd82020-08-07 13:21:17 +0000267
268 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000269 if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) {
270 return;
271 }
Lais Andradee29acd82020-08-07 13:21:17 +0000272 }
273});
274
Lais Andrade6677c6f2025-03-21 09:48:28 -0700275BENCHMARK_WRAPPER(VibratorBench, getSupportedAlwaysOnEffects, {
276 if (!hasCapabilities(IVibrator::CAP_ALWAYS_ON_CONTROL)) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000277 state.SkipWithMessage("always on control unavailable");
278 return;
279 }
280
Lais Andrade6677c6f2025-03-21 09:48:28 -0700281 std::vector<Effect> supportedEffects;
Lais Andradee29acd82020-08-07 13:21:17 +0000282
283 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000284 if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) {
285 return;
286 }
Lais Andradee29acd82020-08-07 13:21:17 +0000287 }
288});
289
Lais Andrade6677c6f2025-03-21 09:48:28 -0700290BENCHMARK_WRAPPER(VibratorBench, getSupportedPrimitives, {
291 std::vector<CompositePrimitive> supportedPrimitives;
Lais Andradee29acd82020-08-07 13:21:17 +0000292
293 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000294 if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) {
295 return;
296 }
Lais Andradee29acd82020-08-07 13:21:17 +0000297 }
298});
299
Lais Andrade6677c6f2025-03-21 09:48:28 -0700300class EffectsVibratorBench : public VibratorBench {
Lais Andradee29acd82020-08-07 13:21:17 +0000301 public:
302 static void DefaultArgs(Benchmark* b) {
303 b->ArgNames({"Effect", "Strength"});
Lais Andrade6677c6f2025-03-21 09:48:28 -0700304 for (const auto& effect : enum_range<Effect>()) {
305 for (const auto& strength : enum_range<EffectStrength>()) {
Lais Andradee29acd82020-08-07 13:21:17 +0000306 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
307 }
308 }
309 }
310
311 protected:
312 auto getEffect(const State& state) const {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700313 return static_cast<Effect>(this->getOtherArg(state, 0));
Lais Andradee29acd82020-08-07 13:21:17 +0000314 }
315
316 auto getStrength(const State& state) const {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700317 return static_cast<EffectStrength>(this->getOtherArg(state, 1));
Lais Andradee29acd82020-08-07 13:21:17 +0000318 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000319
Lais Andrade6677c6f2025-03-21 09:48:28 -0700320 bool isEffectSupported(const Effect& effect) {
321 std::vector<Effect> supported;
Lais Andrade59a5d542024-03-12 11:53:00 +0000322 mVibrator->getSupportedEffects(&supported);
323 return std::find(supported.begin(), supported.end(), effect) != supported.end();
324 }
325
Lais Andrade6677c6f2025-03-21 09:48:28 -0700326 bool isAlwaysOnEffectSupported(const Effect& effect) {
327 std::vector<Effect> supported;
Lais Andrade59a5d542024-03-12 11:53:00 +0000328 mVibrator->getSupportedAlwaysOnEffects(&supported);
329 return std::find(supported.begin(), supported.end(), effect) != supported.end();
330 }
331};
332
Lais Andrade6677c6f2025-03-21 09:48:28 -0700333class SlowEffectsVibratorBench : public EffectsVibratorBench {
Lais Andrade59a5d542024-03-12 11:53:00 +0000334 public:
335 static void DefaultConfig(Benchmark* b) {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700336 EffectsVibratorBench::DefaultConfig(b);
Lais Andrade59a5d542024-03-12 11:53:00 +0000337 SlowBenchConfig(b);
338 }
Lais Andradee29acd82020-08-07 13:21:17 +0000339};
340
Lais Andrade6677c6f2025-03-21 09:48:28 -0700341BENCHMARK_WRAPPER(EffectsVibratorBench, alwaysOnEnable, {
342 if (!hasCapabilities(IVibrator::CAP_ALWAYS_ON_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000343 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000344 return;
345 }
346
347 int32_t id = 1;
348 auto effect = getEffect(state);
349 auto strength = getStrength(state);
350
Lais Andrade59a5d542024-03-12 11:53:00 +0000351 if (!isAlwaysOnEffectSupported(effect)) {
352 state.SkipWithMessage("always on effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000353 return;
354 }
355
356 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000357 // Test
358 if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
359 return;
360 }
361
362 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000363 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000364 if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
365 return;
366 }
367 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000368 }
369});
370
Lais Andrade6677c6f2025-03-21 09:48:28 -0700371BENCHMARK_WRAPPER(EffectsVibratorBench, alwaysOnDisable, {
372 if (!hasCapabilities(IVibrator::CAP_ALWAYS_ON_CONTROL)) {
Adrian Roos77659422024-02-09 17:20:54 +0000373 state.SkipWithMessage("always on control unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000374 return;
375 }
376
377 int32_t id = 1;
378 auto effect = getEffect(state);
379 auto strength = getStrength(state);
380
Lais Andrade59a5d542024-03-12 11:53:00 +0000381 if (!isAlwaysOnEffectSupported(effect)) {
382 state.SkipWithMessage("always on effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000383 return;
384 }
385
386 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000387 // Setup
Lais Andradee29acd82020-08-07 13:21:17 +0000388 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000389 if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) {
390 return;
391 }
Lais Andradee29acd82020-08-07 13:21:17 +0000392 state.ResumeTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000393
394 // Test
395 if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) {
396 return;
397 }
Lais Andradee29acd82020-08-07 13:21:17 +0000398 }
399});
400
Lais Andrade6677c6f2025-03-21 09:48:28 -0700401BENCHMARK_WRAPPER(SlowEffectsVibratorBench, perform, {
Lais Andradee29acd82020-08-07 13:21:17 +0000402 auto effect = getEffect(state);
403 auto strength = getStrength(state);
Lais Andradee29acd82020-08-07 13:21:17 +0000404
Lais Andrade59a5d542024-03-12 11:53:00 +0000405 if (!isEffectSupported(effect)) {
406 state.SkipWithMessage("effect unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000407 return;
408 }
409
Lais Andrade59a5d542024-03-12 11:53:00 +0000410 int32_t lengthMs = 0;
411
Lais Andradee29acd82020-08-07 13:21:17 +0000412 for (auto _ : state) {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700413 auto cb = hasCapabilities(IVibrator::CAP_PERFORM_CALLBACK)
Lais Andrade28c81f12024-06-24 14:32:22 +0100414 ? ndk::SharedRefBase::make<HalCallback>()
415 : nullptr;
Lais Andradea5131c52024-06-12 16:39:29 +0100416 // Grab the future before callback promise is destroyed by the HAL.
417 auto cbFuture = cb ? cb->getFuture() : std::future<void>();
Lais Andrade59a5d542024-03-12 11:53:00 +0000418
419 // Test
420 if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) {
421 return;
422 }
423
424 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000425 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000426 if (shouldSkipWithError(state, mVibrator->off())) {
427 return;
428 }
Lais Andradea5131c52024-06-12 16:39:29 +0100429 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000430 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000431 }
432});
433
Lais Andrade6677c6f2025-03-21 09:48:28 -0700434class PrimitivesVibratorBench : public VibratorBench {
Lais Andradee29acd82020-08-07 13:21:17 +0000435 public:
436 static void DefaultArgs(Benchmark* b) {
437 b->ArgNames({"Primitive"});
Lais Andrade6677c6f2025-03-21 09:48:28 -0700438 for (const auto& primitive : enum_range<CompositePrimitive>()) {
Lais Andradee29acd82020-08-07 13:21:17 +0000439 b->Args({static_cast<long>(primitive)});
440 }
441 }
442
443 protected:
444 auto getPrimitive(const State& state) const {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700445 return static_cast<CompositePrimitive>(this->getOtherArg(state, 0));
Lais Andradee29acd82020-08-07 13:21:17 +0000446 }
Lais Andrade59a5d542024-03-12 11:53:00 +0000447
Lais Andrade6677c6f2025-03-21 09:48:28 -0700448 bool isPrimitiveSupported(const CompositePrimitive& primitive) {
449 std::vector<CompositePrimitive> supported;
Lais Andrade59a5d542024-03-12 11:53:00 +0000450 mVibrator->getSupportedPrimitives(&supported);
451 return std::find(supported.begin(), supported.end(), primitive) != supported.end();
452 }
453};
454
Lais Andrade6677c6f2025-03-21 09:48:28 -0700455class SlowPrimitivesVibratorBench : public PrimitivesVibratorBench {
Lais Andrade59a5d542024-03-12 11:53:00 +0000456 public:
457 static void DefaultConfig(Benchmark* b) {
Lais Andrade6677c6f2025-03-21 09:48:28 -0700458 PrimitivesVibratorBench::DefaultConfig(b);
459 SlowBenchConfig(b);
Lais Andrade59a5d542024-03-12 11:53:00 +0000460 }
Lais Andradee29acd82020-08-07 13:21:17 +0000461};
462
Lais Andrade6677c6f2025-03-21 09:48:28 -0700463BENCHMARK_WRAPPER(PrimitivesVibratorBench, getCompositionDelayMax, {
Lais Andradee29acd82020-08-07 13:21:17 +0000464 int32_t ms = 0;
465
466 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000467 if (shouldSkipWithError(state, mVibrator->getCompositionDelayMax(&ms))) {
468 return;
469 }
Lais Andradee29acd82020-08-07 13:21:17 +0000470 }
471});
472
Lais Andrade6677c6f2025-03-21 09:48:28 -0700473BENCHMARK_WRAPPER(PrimitivesVibratorBench, getCompositionSizeMax, {
Lais Andradee29acd82020-08-07 13:21:17 +0000474 int32_t size = 0;
475
476 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000477 if (shouldSkipWithError(state, mVibrator->getCompositionSizeMax(&size))) {
478 return;
479 }
Lais Andradee29acd82020-08-07 13:21:17 +0000480 }
481});
482
Lais Andrade6677c6f2025-03-21 09:48:28 -0700483BENCHMARK_WRAPPER(PrimitivesVibratorBench, getPrimitiveDuration, {
484 if (!hasCapabilities(IVibrator::CAP_COMPOSE_EFFECTS)) {
Adrian Roos77659422024-02-09 17:20:54 +0000485 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000486 return;
487 }
488
489 auto primitive = getPrimitive(state);
490 int32_t ms = 0;
491
Lais Andrade59a5d542024-03-12 11:53:00 +0000492 if (!isPrimitiveSupported(primitive)) {
493 state.SkipWithMessage("primitive unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000494 return;
495 }
496
497 for (auto _ : state) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000498 if (shouldSkipWithError(state, mVibrator->getPrimitiveDuration(primitive, &ms))) {
499 return;
500 }
Lais Andradee29acd82020-08-07 13:21:17 +0000501 }
502});
503
Lais Andrade6677c6f2025-03-21 09:48:28 -0700504BENCHMARK_WRAPPER(SlowPrimitivesVibratorBench, compose, {
505 if (!hasCapabilities(IVibrator::CAP_COMPOSE_EFFECTS)) {
Adrian Roos77659422024-02-09 17:20:54 +0000506 state.SkipWithMessage("compose effects unavailable");
Lais Andradee29acd82020-08-07 13:21:17 +0000507 return;
508 }
509
Lais Andrade6677c6f2025-03-21 09:48:28 -0700510 CompositeEffect effect;
Lais Andradee29acd82020-08-07 13:21:17 +0000511 effect.primitive = getPrimitive(state);
512 effect.scale = 1.0f;
513 effect.delayMs = 0;
514
Lais Andrade6677c6f2025-03-21 09:48:28 -0700515 if (effect.primitive == CompositePrimitive::NOOP) {
Lais Andrade59a5d542024-03-12 11:53:00 +0000516 state.SkipWithMessage("skipping primitive NOOP");
517 return;
518 }
519 if (!isPrimitiveSupported(effect.primitive)) {
520 state.SkipWithMessage("primitive unsupported");
Lais Andradee29acd82020-08-07 13:21:17 +0000521 return;
522 }
523
Lais Andrade6677c6f2025-03-21 09:48:28 -0700524 std::vector<CompositeEffect> effects;
Lais Andradee29acd82020-08-07 13:21:17 +0000525 effects.push_back(effect);
526
527 for (auto _ : state) {
Lais Andrade28c81f12024-06-24 14:32:22 +0100528 auto cb = ndk::SharedRefBase::make<HalCallback>();
Lais Andradea5131c52024-06-12 16:39:29 +0100529 // Grab the future before callback promise is moved and destroyed by the HAL.
530 auto cbFuture = cb->getFuture();
Lais Andrade59a5d542024-03-12 11:53:00 +0000531
532 // Test
533 if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) {
534 return;
535 }
536
537 // Cleanup
Lais Andradee29acd82020-08-07 13:21:17 +0000538 state.PauseTiming();
Lais Andrade59a5d542024-03-12 11:53:00 +0000539 if (shouldSkipWithError(state, mVibrator->off())) {
540 return;
541 }
Lais Andradea5131c52024-06-12 16:39:29 +0100542 waitForComplete(cbFuture);
Lais Andrade59a5d542024-03-12 11:53:00 +0000543 state.ResumeTiming();
Lais Andradee29acd82020-08-07 13:21:17 +0000544 }
545});
546
547BENCHMARK_MAIN();