Loading vibrator/bench/benchmark.cpp +359 −131 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <android/hardware/vibrator/BnVibratorCallback.h> #include <android/hardware/vibrator/IVibrator.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> #include <future> using ::android::enum_range; using ::android::sp; Loading @@ -31,9 +33,8 @@ using ::benchmark::Fixture; using ::benchmark::kMicrosecond; using ::benchmark::State; using ::benchmark::internal::Benchmark; using ::std::chrono::duration; using ::std::chrono::duration_cast; using ::std::chrono::high_resolution_clock; using namespace ::std::chrono_literals; namespace Aidl = ::android::hardware::vibrator; namespace V1_0 = ::android::hardware::vibrator::V1_0; Loading @@ -41,15 +42,29 @@ namespace V1_1 = ::android::hardware::vibrator::V1_1; namespace V1_2 = ::android::hardware::vibrator::V1_2; namespace V1_3 = ::android::hardware::vibrator::V1_3; // Fixed number of iterations for benchmarks that trigger a vibration on the loop. // They require slow cleanup to ensure a stable state on each run and less noisy metrics. static constexpr auto VIBRATION_ITERATIONS = 500; // Timeout to wait for vibration callback completion. static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms; // Max duration the vibrator can be turned on, in milliseconds. static constexpr uint32_t MAX_ON_DURATION_MS = UINT16_MAX; template <typename I> class BaseBench : public Fixture { public: void TearDown(State& /*state*/) override { if (!mVibrator) { return; void SetUp(State& /*state*/) override { android::ProcessState::self()->setThreadPoolMaxThreadCount(1); android::ProcessState::self()->startThreadPool(); } void TearDown(State& /*state*/) override { if (mVibrator) { mVibrator->off(); } } static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); } Loading @@ -66,7 +81,19 @@ class BaseBench : public Fixture { template <typename I> class VibratorBench : public BaseBench<I> { public: void SetUp(State& /*state*/) override { this->mVibrator = I::getService(); } void SetUp(State& state) override { BaseBench<I>::SetUp(state); this->mVibrator = I::getService(); } protected: bool shouldSkipWithError(State& state, const android::hardware::Return<V1_0::Status>&& ret) { if (!ret.isOk()) { state.SkipWithError(ret.description()); return true; } return false; } }; enum class EmptyEnum : uint32_t; Loading Loading @@ -118,16 +145,25 @@ class VibratorEffectsBench : public VibratorBench<I> { }); if (!supported) { state->SkipWithMessage("performApi returned UNSUPPORTED_OPERATION"); state->SkipWithMessage("effect unsupported"); return; } for (auto _ : *state) { state->ResumeTiming(); (*this->mVibrator.*performApi)(effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {}); // Test auto ret = (*this->mVibrator.*performApi)( effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {}); // Cleanup state->PauseTiming(); this->mVibrator->off(); if (!ret.isOk()) { state->SkipWithError(ret.description()); return; } if (this->shouldSkipWithError(*state, this->mVibrator->off())) { return; } state->ResumeTiming(); } } Loading Loading @@ -157,24 +193,38 @@ class VibratorEffectsBench : public VibratorBench<I> { using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>; BENCHMARK_WRAPPER(VibratorBench_V1_0, on, { uint32_t ms = UINT32_MAX; auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { state.ResumeTiming(); mVibrator->on(ms); // Test if (shouldSkipWithError(state, mVibrator->on(ms))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_V1_0, off, { uint32_t ms = UINT32_MAX; auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { // Setup state.PauseTiming(); mVibrator->on(ms); if (shouldSkipWithError(state, mVibrator->on(ms))) { return; } state.ResumeTiming(); mVibrator->off(); // Test if (shouldSkipWithError(state, mVibrator->off())) { return; } } }); Loading @@ -185,20 +235,23 @@ BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, { }); BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, { auto ms = MAX_ON_DURATION_MS; uint8_t amplitude = UINT8_MAX; if (!mVibrator->supportsAmplitudeControl()) { state.SkipWithMessage("Amplitude control unavailable"); state.SkipWithMessage("amplitude control unavailable"); return; } mVibrator->on(UINT32_MAX); if (shouldSkipWithError(state, mVibrator->on(ms))) { return; } for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->off(); }); using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>; Loading @@ -218,7 +271,15 @@ using VibratorEffectsBench_V1_2 = BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2, { performBench(&state, &V1_2::IVibrator::perform_1_2); }); using VibratorBench_V1_3 = VibratorBench<V1_3::IVibrator>; class VibratorBench_V1_3 : public VibratorBench<V1_3::IVibrator> { public: void TearDown(State& state) override { VibratorBench::TearDown(state); if (mVibrator) { mVibrator->setExternalControl(false); } } }; BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, { for (auto _ : state) { Loading @@ -227,18 +288,23 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, { }); BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, { bool enable = true; if (!mVibrator->supportsExternalControl()) { state.SkipWithMessage("external control unavailable"); return; } for (auto _ : state) { state.ResumeTiming(); mVibrator->setExternalControl(enable); // Test if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } // Cleanup state.PauseTiming(); mVibrator->setExternalControl(false); if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) { return; } state.ResumeTiming(); } }); Loading @@ -248,13 +314,13 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, { return; } mVibrator->setExternalControl(true); if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } for (auto _ : state) { mVibrator->supportsAmplitudeControl(); } mVibrator->setExternalControl(false); }); BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { Loading @@ -265,7 +331,9 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { return; } mVibrator->setExternalControl(true); if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } if (!mVibrator->supportsAmplitudeControl()) { state.SkipWithMessage("amplitude control unavailable"); Loading @@ -273,10 +341,10 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { } for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->setExternalControl(false); }); using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>; Loading @@ -286,9 +354,42 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3, class VibratorBench_Aidl : public BaseBench<Aidl::IVibrator> { public: void SetUp(State& /*state*/) override { void SetUp(State& state) override { BaseBench::SetUp(state); this->mVibrator = android::waitForVintfService<Aidl::IVibrator>(); } void TearDown(State& state) override { BaseBench::TearDown(state); if (mVibrator) { mVibrator->setExternalControl(false); } } protected: int32_t hasCapabilities(int32_t capabilities) { int32_t deviceCapabilities = 0; this->mVibrator->getCapabilities(&deviceCapabilities); return (deviceCapabilities & capabilities) == capabilities; } bool shouldSkipWithError(State& state, const android::binder::Status&& status) { if (!status.isOk()) { state.SkipWithError(status.toString8().c_str()); return true; } return false; } static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); } }; class SlowVibratorBench_Aidl : public VibratorBench_Aidl { public: static void DefaultConfig(Benchmark* b) { VibratorBench_Aidl::DefaultConfig(b); SlowBenchConfig(b); } }; class HalCallback : public Aidl::BnVibratorCallback { Loading @@ -296,30 +397,70 @@ class HalCallback : public Aidl::BnVibratorCallback { HalCallback() = default; ~HalCallback() = default; android::binder::Status onComplete() override { return android::binder::Status::ok(); } }; android::binder::Status onComplete() override { mPromise.set_value(); return android::binder::Status::ok(); } BENCHMARK_WRAPPER(VibratorBench_Aidl, on, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); void waitForComplete() { // Wait until the HAL has finished processing previous vibration before starting a new one, // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest // HAL implementations are waiting on previous vibration cleanup and might be significantly // slower, so make sure we measure vibrations on a clean slate. mPromise.get_future().wait_for(VIBRATION_CALLBACK_TIMEOUT); } int32_t ms = INT32_MAX; auto cb = (capabilities & Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; private: std::promise<void> mPromise; }; BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, on, { auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { state.ResumeTiming(); mVibrator->on(ms, cb); auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; // Test if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } if (cb) { cb->waitForComplete(); } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, off, { BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, off, { auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; // Setup state.PauseTiming(); mVibrator->on(INT32_MAX, nullptr); if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { return; } state.ResumeTiming(); // Test if (shouldSkipWithError(state, mVibrator->off())) { return; } // Cleanup state.PauseTiming(); if (cb) { cb->waitForComplete(); } state.ResumeTiming(); mVibrator->off(); } }); Loading @@ -327,76 +468,102 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, { int32_t capabilities = 0; for (auto _ : state) { mVibrator->getCapabilities(&capabilities); if (shouldSkipWithError(state, mVibrator->getCapabilities(&capabilities))) { return; } } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_AMPLITUDE_CONTROL) == 0) { auto ms = MAX_ON_DURATION_MS; float amplitude = 1.0f; if (!hasCapabilities(Aidl::IVibrator::CAP_AMPLITUDE_CONTROL)) { state.SkipWithMessage("amplitude control unavailable"); return; } float amplitude = 1.0f; mVibrator->on(INT32_MAX, nullptr); auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { return; } for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->off(); shouldSkipWithError(state, mVibrator->off()); if (cb) { cb->waitForComplete(); } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_EXTERNAL_CONTROL)) { state.SkipWithMessage("external control unavailable"); return; } for (auto _ : state) { state.ResumeTiming(); mVibrator->setExternalControl(true); // Test if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } // Cleanup state.PauseTiming(); mVibrator->setExternalControl(false); if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) { return; } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0 || (capabilities & Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) == 0) { auto externalControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_CONTROL); auto externalAmplitudeControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL); if (!hasCapabilities(externalControl | externalAmplitudeControl)) { state.SkipWithMessage("external amplitude control unavailable"); return; } float amplitude = 1.0f; mVibrator->setExternalControl(true); if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } float amplitude = 1.0f; for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->setExternalControl(false); }); BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, { std::vector<Aidl::Effect> supportedEffects; for (auto _ : state) { mVibrator->getSupportedEffects(&supportedEffects); if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) { return; } } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, { if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } std::vector<Aidl::Effect> supportedEffects; for (auto _ : state) { mVibrator->getSupportedAlwaysOnEffects(&supportedEffects); if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) { return; } } }); Loading @@ -404,7 +571,9 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, { std::vector<Aidl::CompositePrimitive> supportedPrimitives; for (auto _ : state) { mVibrator->getSupportedPrimitives(&supportedPrimitives); if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) { return; } } }); Loading @@ -427,12 +596,30 @@ class VibratorEffectsBench_Aidl : public VibratorBench_Aidl { auto getStrength(const State& state) const { return static_cast<Aidl::EffectStrength>(this->getOtherArg(state, 1)); } bool isEffectSupported(const Aidl::Effect& effect) { std::vector<Aidl::Effect> supported; mVibrator->getSupportedEffects(&supported); return std::find(supported.begin(), supported.end(), effect) != supported.end(); } bool isAlwaysOnEffectSupported(const Aidl::Effect& effect) { std::vector<Aidl::Effect> supported; mVibrator->getSupportedAlwaysOnEffects(&supported); return std::find(supported.begin(), supported.end(), effect) != supported.end(); } }; class SlowVibratorEffectsBench_Aidl : public VibratorEffectsBench_Aidl { public: static void DefaultConfig(Benchmark* b) { VibratorEffectsBench_Aidl::DefaultConfig(b); SlowBenchConfig(b); } }; BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } Loading @@ -441,25 +628,28 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, { auto effect = getEffect(state); auto strength = getStrength(state); std::vector<Aidl::Effect> supported; mVibrator->getSupportedAlwaysOnEffects(&supported); if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { state.SkipWithMessage("always on effects unavailable"); if (!isAlwaysOnEffectSupported(effect)) { state.SkipWithMessage("always on effect unsupported"); return; } for (auto _ : state) { state.ResumeTiming(); mVibrator->alwaysOnEnable(id, effect, strength); // Test if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) { return; } // Cleanup state.PauseTiming(); mVibrator->alwaysOnDisable(id); if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) { return; } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } Loading @@ -468,42 +658,55 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, { auto effect = getEffect(state); auto strength = getStrength(state); std::vector<Aidl::Effect> supported; mVibrator->getSupportedAlwaysOnEffects(&supported); if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { state.SkipWithMessage("always on effects unavailable"); if (!isAlwaysOnEffectSupported(effect)) { state.SkipWithMessage("always on effect unsupported"); return; } for (auto _ : state) { // Setup state.PauseTiming(); mVibrator->alwaysOnEnable(id, effect, strength); if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) { return; } state.ResumeTiming(); mVibrator->alwaysOnDisable(id); // Test if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) { return; } } }); BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, perform, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); BENCHMARK_WRAPPER(SlowVibratorEffectsBench_Aidl, perform, { auto effect = getEffect(state); auto strength = getStrength(state); auto cb = (capabilities & Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr; int32_t lengthMs = 0; std::vector<Aidl::Effect> supported; mVibrator->getSupportedEffects(&supported); if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { state.SkipWithMessage("effects unavailable"); if (!isEffectSupported(effect)) { state.SkipWithMessage("effect unsupported"); return; } int32_t lengthMs = 0; for (auto _ : state) { state.ResumeTiming(); mVibrator->perform(effect, strength, cb, &lengthMs); auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr; // Test if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } if (cb) { cb->waitForComplete(); } state.ResumeTiming(); } }); Loading @@ -520,13 +723,29 @@ class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl { auto getPrimitive(const State& state) const { return static_cast<Aidl::CompositePrimitive>(this->getOtherArg(state, 0)); } bool isPrimitiveSupported(const Aidl::CompositePrimitive& primitive) { std::vector<Aidl::CompositePrimitive> supported; mVibrator->getSupportedPrimitives(&supported); return std::find(supported.begin(), supported.end(), primitive) != supported.end(); } }; class SlowVibratorPrimitivesBench_Aidl : public VibratorPrimitivesBench_Aidl { public: static void DefaultConfig(Benchmark* b) { VibratorPrimitivesBench_Aidl::DefaultConfig(b); SlowBenchConfig(b); } }; BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, { int32_t ms = 0; for (auto _ : state) { mVibrator->getCompositionDelayMax(&ms); if (shouldSkipWithError(state, mVibrator->getCompositionDelayMax(&ms))) { return; } } }); Loading @@ -534,14 +753,14 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, { int32_t size = 0; for (auto _ : state) { mVibrator->getCompositionSizeMax(&size); if (shouldSkipWithError(state, mVibrator->getCompositionSizeMax(&size))) { return; } } }); BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) { state.SkipWithMessage("compose effects unavailable"); return; } Loading @@ -549,22 +768,20 @@ BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, { auto primitive = getPrimitive(state); int32_t ms = 0; std::vector<Aidl::CompositePrimitive> supported; mVibrator->getSupportedPrimitives(&supported); if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) { state.SkipWithMessage("supported primitives unavailable"); if (!isPrimitiveSupported(primitive)) { state.SkipWithMessage("primitive unsupported"); return; } for (auto _ : state) { mVibrator->getPrimitiveDuration(primitive, &ms); if (shouldSkipWithError(state, mVibrator->getPrimitiveDuration(primitive, &ms))) { return; } } }); BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { BENCHMARK_WRAPPER(SlowVibratorPrimitivesBench_Aidl, compose, { if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) { state.SkipWithMessage("compose effects unavailable"); return; } Loading @@ -574,22 +791,33 @@ BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, { effect.scale = 1.0f; effect.delayMs = 0; std::vector<Aidl::CompositePrimitive> supported; mVibrator->getSupportedPrimitives(&supported); if (std::find(supported.begin(), supported.end(), effect.primitive) == supported.end()) { state.SkipWithMessage("supported primitives unavailable"); if (effect.primitive == Aidl::CompositePrimitive::NOOP) { state.SkipWithMessage("skipping primitive NOOP"); return; } if (!isPrimitiveSupported(effect.primitive)) { state.SkipWithMessage("primitive unsupported"); return; } auto cb = new HalCallback(); std::vector<Aidl::CompositeEffect> effects; effects.push_back(effect); for (auto _ : state) { state.ResumeTiming(); mVibrator->compose(effects, cb); auto cb = new HalCallback(); // Test if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } cb->waitForComplete(); state.ResumeTiming(); } }); Loading Loading
vibrator/bench/benchmark.cpp +359 −131 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <android/hardware/vibrator/BnVibratorCallback.h> #include <android/hardware/vibrator/IVibrator.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> #include <future> using ::android::enum_range; using ::android::sp; Loading @@ -31,9 +33,8 @@ using ::benchmark::Fixture; using ::benchmark::kMicrosecond; using ::benchmark::State; using ::benchmark::internal::Benchmark; using ::std::chrono::duration; using ::std::chrono::duration_cast; using ::std::chrono::high_resolution_clock; using namespace ::std::chrono_literals; namespace Aidl = ::android::hardware::vibrator; namespace V1_0 = ::android::hardware::vibrator::V1_0; Loading @@ -41,15 +42,29 @@ namespace V1_1 = ::android::hardware::vibrator::V1_1; namespace V1_2 = ::android::hardware::vibrator::V1_2; namespace V1_3 = ::android::hardware::vibrator::V1_3; // Fixed number of iterations for benchmarks that trigger a vibration on the loop. // They require slow cleanup to ensure a stable state on each run and less noisy metrics. static constexpr auto VIBRATION_ITERATIONS = 500; // Timeout to wait for vibration callback completion. static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms; // Max duration the vibrator can be turned on, in milliseconds. static constexpr uint32_t MAX_ON_DURATION_MS = UINT16_MAX; template <typename I> class BaseBench : public Fixture { public: void TearDown(State& /*state*/) override { if (!mVibrator) { return; void SetUp(State& /*state*/) override { android::ProcessState::self()->setThreadPoolMaxThreadCount(1); android::ProcessState::self()->startThreadPool(); } void TearDown(State& /*state*/) override { if (mVibrator) { mVibrator->off(); } } static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); } Loading @@ -66,7 +81,19 @@ class BaseBench : public Fixture { template <typename I> class VibratorBench : public BaseBench<I> { public: void SetUp(State& /*state*/) override { this->mVibrator = I::getService(); } void SetUp(State& state) override { BaseBench<I>::SetUp(state); this->mVibrator = I::getService(); } protected: bool shouldSkipWithError(State& state, const android::hardware::Return<V1_0::Status>&& ret) { if (!ret.isOk()) { state.SkipWithError(ret.description()); return true; } return false; } }; enum class EmptyEnum : uint32_t; Loading Loading @@ -118,16 +145,25 @@ class VibratorEffectsBench : public VibratorBench<I> { }); if (!supported) { state->SkipWithMessage("performApi returned UNSUPPORTED_OPERATION"); state->SkipWithMessage("effect unsupported"); return; } for (auto _ : *state) { state->ResumeTiming(); (*this->mVibrator.*performApi)(effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {}); // Test auto ret = (*this->mVibrator.*performApi)( effect, strength, [](Status /*status*/, uint32_t /*lengthMs*/) {}); // Cleanup state->PauseTiming(); this->mVibrator->off(); if (!ret.isOk()) { state->SkipWithError(ret.description()); return; } if (this->shouldSkipWithError(*state, this->mVibrator->off())) { return; } state->ResumeTiming(); } } Loading Loading @@ -157,24 +193,38 @@ class VibratorEffectsBench : public VibratorBench<I> { using VibratorBench_V1_0 = VibratorBench<V1_0::IVibrator>; BENCHMARK_WRAPPER(VibratorBench_V1_0, on, { uint32_t ms = UINT32_MAX; auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { state.ResumeTiming(); mVibrator->on(ms); // Test if (shouldSkipWithError(state, mVibrator->on(ms))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_V1_0, off, { uint32_t ms = UINT32_MAX; auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { // Setup state.PauseTiming(); mVibrator->on(ms); if (shouldSkipWithError(state, mVibrator->on(ms))) { return; } state.ResumeTiming(); mVibrator->off(); // Test if (shouldSkipWithError(state, mVibrator->off())) { return; } } }); Loading @@ -185,20 +235,23 @@ BENCHMARK_WRAPPER(VibratorBench_V1_0, supportsAmplitudeControl, { }); BENCHMARK_WRAPPER(VibratorBench_V1_0, setAmplitude, { auto ms = MAX_ON_DURATION_MS; uint8_t amplitude = UINT8_MAX; if (!mVibrator->supportsAmplitudeControl()) { state.SkipWithMessage("Amplitude control unavailable"); state.SkipWithMessage("amplitude control unavailable"); return; } mVibrator->on(UINT32_MAX); if (shouldSkipWithError(state, mVibrator->on(ms))) { return; } for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->off(); }); using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>; Loading @@ -218,7 +271,15 @@ using VibratorEffectsBench_V1_2 = BENCHMARK_WRAPPER(VibratorEffectsBench_V1_2, perform_1_2, { performBench(&state, &V1_2::IVibrator::perform_1_2); }); using VibratorBench_V1_3 = VibratorBench<V1_3::IVibrator>; class VibratorBench_V1_3 : public VibratorBench<V1_3::IVibrator> { public: void TearDown(State& state) override { VibratorBench::TearDown(state); if (mVibrator) { mVibrator->setExternalControl(false); } } }; BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, { for (auto _ : state) { Loading @@ -227,18 +288,23 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalControl, { }); BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalControl, { bool enable = true; if (!mVibrator->supportsExternalControl()) { state.SkipWithMessage("external control unavailable"); return; } for (auto _ : state) { state.ResumeTiming(); mVibrator->setExternalControl(enable); // Test if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } // Cleanup state.PauseTiming(); mVibrator->setExternalControl(false); if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) { return; } state.ResumeTiming(); } }); Loading @@ -248,13 +314,13 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, supportsExternalAmplitudeControl, { return; } mVibrator->setExternalControl(true); if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } for (auto _ : state) { mVibrator->supportsAmplitudeControl(); } mVibrator->setExternalControl(false); }); BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { Loading @@ -265,7 +331,9 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { return; } mVibrator->setExternalControl(true); if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } if (!mVibrator->supportsAmplitudeControl()) { state.SkipWithMessage("amplitude control unavailable"); Loading @@ -273,10 +341,10 @@ BENCHMARK_WRAPPER(VibratorBench_V1_3, setExternalAmplitude, { } for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->setExternalControl(false); }); using VibratorEffectsBench_V1_3 = VibratorEffectsBench<V1_3::IVibrator, V1_3::Effect, V1_2::Effect>; Loading @@ -286,9 +354,42 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_V1_3, perform_1_3, class VibratorBench_Aidl : public BaseBench<Aidl::IVibrator> { public: void SetUp(State& /*state*/) override { void SetUp(State& state) override { BaseBench::SetUp(state); this->mVibrator = android::waitForVintfService<Aidl::IVibrator>(); } void TearDown(State& state) override { BaseBench::TearDown(state); if (mVibrator) { mVibrator->setExternalControl(false); } } protected: int32_t hasCapabilities(int32_t capabilities) { int32_t deviceCapabilities = 0; this->mVibrator->getCapabilities(&deviceCapabilities); return (deviceCapabilities & capabilities) == capabilities; } bool shouldSkipWithError(State& state, const android::binder::Status&& status) { if (!status.isOk()) { state.SkipWithError(status.toString8().c_str()); return true; } return false; } static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); } }; class SlowVibratorBench_Aidl : public VibratorBench_Aidl { public: static void DefaultConfig(Benchmark* b) { VibratorBench_Aidl::DefaultConfig(b); SlowBenchConfig(b); } }; class HalCallback : public Aidl::BnVibratorCallback { Loading @@ -296,30 +397,70 @@ class HalCallback : public Aidl::BnVibratorCallback { HalCallback() = default; ~HalCallback() = default; android::binder::Status onComplete() override { return android::binder::Status::ok(); } }; android::binder::Status onComplete() override { mPromise.set_value(); return android::binder::Status::ok(); } BENCHMARK_WRAPPER(VibratorBench_Aidl, on, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); void waitForComplete() { // Wait until the HAL has finished processing previous vibration before starting a new one, // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest // HAL implementations are waiting on previous vibration cleanup and might be significantly // slower, so make sure we measure vibrations on a clean slate. mPromise.get_future().wait_for(VIBRATION_CALLBACK_TIMEOUT); } int32_t ms = INT32_MAX; auto cb = (capabilities & Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; private: std::promise<void> mPromise; }; BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, on, { auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { state.ResumeTiming(); mVibrator->on(ms, cb); auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; // Test if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } if (cb) { cb->waitForComplete(); } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, off, { BENCHMARK_WRAPPER(SlowVibratorBench_Aidl, off, { auto ms = MAX_ON_DURATION_MS; for (auto _ : state) { auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; // Setup state.PauseTiming(); mVibrator->on(INT32_MAX, nullptr); if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { return; } state.ResumeTiming(); // Test if (shouldSkipWithError(state, mVibrator->off())) { return; } // Cleanup state.PauseTiming(); if (cb) { cb->waitForComplete(); } state.ResumeTiming(); mVibrator->off(); } }); Loading @@ -327,76 +468,102 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getCapabilities, { int32_t capabilities = 0; for (auto _ : state) { mVibrator->getCapabilities(&capabilities); if (shouldSkipWithError(state, mVibrator->getCapabilities(&capabilities))) { return; } } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setAmplitude, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_AMPLITUDE_CONTROL) == 0) { auto ms = MAX_ON_DURATION_MS; float amplitude = 1.0f; if (!hasCapabilities(Aidl::IVibrator::CAP_AMPLITUDE_CONTROL)) { state.SkipWithMessage("amplitude control unavailable"); return; } float amplitude = 1.0f; mVibrator->on(INT32_MAX, nullptr); auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr; if (shouldSkipWithError(state, mVibrator->on(ms, cb))) { return; } for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->off(); shouldSkipWithError(state, mVibrator->off()); if (cb) { cb->waitForComplete(); } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalControl, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_EXTERNAL_CONTROL)) { state.SkipWithMessage("external control unavailable"); return; } for (auto _ : state) { state.ResumeTiming(); mVibrator->setExternalControl(true); // Test if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } // Cleanup state.PauseTiming(); mVibrator->setExternalControl(false); if (shouldSkipWithError(state, mVibrator->setExternalControl(false))) { return; } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, setExternalAmplitude, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_EXTERNAL_CONTROL) == 0 || (capabilities & Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) == 0) { auto externalControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_CONTROL); auto externalAmplitudeControl = static_cast<int32_t>(Aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL); if (!hasCapabilities(externalControl | externalAmplitudeControl)) { state.SkipWithMessage("external amplitude control unavailable"); return; } float amplitude = 1.0f; mVibrator->setExternalControl(true); if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) { return; } float amplitude = 1.0f; for (auto _ : state) { mVibrator->setAmplitude(amplitude); if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) { return; } } mVibrator->setExternalControl(false); }); BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedEffects, { std::vector<Aidl::Effect> supportedEffects; for (auto _ : state) { mVibrator->getSupportedEffects(&supportedEffects); if (shouldSkipWithError(state, mVibrator->getSupportedEffects(&supportedEffects))) { return; } } }); BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedAlwaysOnEffects, { if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } std::vector<Aidl::Effect> supportedEffects; for (auto _ : state) { mVibrator->getSupportedAlwaysOnEffects(&supportedEffects); if (shouldSkipWithError(state, mVibrator->getSupportedAlwaysOnEffects(&supportedEffects))) { return; } } }); Loading @@ -404,7 +571,9 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getSupportedPrimitives, { std::vector<Aidl::CompositePrimitive> supportedPrimitives; for (auto _ : state) { mVibrator->getSupportedPrimitives(&supportedPrimitives); if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) { return; } } }); Loading @@ -427,12 +596,30 @@ class VibratorEffectsBench_Aidl : public VibratorBench_Aidl { auto getStrength(const State& state) const { return static_cast<Aidl::EffectStrength>(this->getOtherArg(state, 1)); } bool isEffectSupported(const Aidl::Effect& effect) { std::vector<Aidl::Effect> supported; mVibrator->getSupportedEffects(&supported); return std::find(supported.begin(), supported.end(), effect) != supported.end(); } bool isAlwaysOnEffectSupported(const Aidl::Effect& effect) { std::vector<Aidl::Effect> supported; mVibrator->getSupportedAlwaysOnEffects(&supported); return std::find(supported.begin(), supported.end(), effect) != supported.end(); } }; class SlowVibratorEffectsBench_Aidl : public VibratorEffectsBench_Aidl { public: static void DefaultConfig(Benchmark* b) { VibratorEffectsBench_Aidl::DefaultConfig(b); SlowBenchConfig(b); } }; BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } Loading @@ -441,25 +628,28 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnEnable, { auto effect = getEffect(state); auto strength = getStrength(state); std::vector<Aidl::Effect> supported; mVibrator->getSupportedAlwaysOnEffects(&supported); if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { state.SkipWithMessage("always on effects unavailable"); if (!isAlwaysOnEffectSupported(effect)) { state.SkipWithMessage("always on effect unsupported"); return; } for (auto _ : state) { state.ResumeTiming(); mVibrator->alwaysOnEnable(id, effect, strength); // Test if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) { return; } // Cleanup state.PauseTiming(); mVibrator->alwaysOnDisable(id); if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) { return; } state.ResumeTiming(); } }); BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_ALWAYS_ON_CONTROL)) { state.SkipWithMessage("always on control unavailable"); return; } Loading @@ -468,42 +658,55 @@ BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, alwaysOnDisable, { auto effect = getEffect(state); auto strength = getStrength(state); std::vector<Aidl::Effect> supported; mVibrator->getSupportedAlwaysOnEffects(&supported); if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { state.SkipWithMessage("always on effects unavailable"); if (!isAlwaysOnEffectSupported(effect)) { state.SkipWithMessage("always on effect unsupported"); return; } for (auto _ : state) { // Setup state.PauseTiming(); mVibrator->alwaysOnEnable(id, effect, strength); if (shouldSkipWithError(state, mVibrator->alwaysOnEnable(id, effect, strength))) { return; } state.ResumeTiming(); mVibrator->alwaysOnDisable(id); // Test if (shouldSkipWithError(state, mVibrator->alwaysOnDisable(id))) { return; } } }); BENCHMARK_WRAPPER(VibratorEffectsBench_Aidl, perform, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); BENCHMARK_WRAPPER(SlowVibratorEffectsBench_Aidl, perform, { auto effect = getEffect(state); auto strength = getStrength(state); auto cb = (capabilities & Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr; int32_t lengthMs = 0; std::vector<Aidl::Effect> supported; mVibrator->getSupportedEffects(&supported); if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { state.SkipWithMessage("effects unavailable"); if (!isEffectSupported(effect)) { state.SkipWithMessage("effect unsupported"); return; } int32_t lengthMs = 0; for (auto _ : state) { state.ResumeTiming(); mVibrator->perform(effect, strength, cb, &lengthMs); auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback() : nullptr; // Test if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } if (cb) { cb->waitForComplete(); } state.ResumeTiming(); } }); Loading @@ -520,13 +723,29 @@ class VibratorPrimitivesBench_Aidl : public VibratorBench_Aidl { auto getPrimitive(const State& state) const { return static_cast<Aidl::CompositePrimitive>(this->getOtherArg(state, 0)); } bool isPrimitiveSupported(const Aidl::CompositePrimitive& primitive) { std::vector<Aidl::CompositePrimitive> supported; mVibrator->getSupportedPrimitives(&supported); return std::find(supported.begin(), supported.end(), primitive) != supported.end(); } }; class SlowVibratorPrimitivesBench_Aidl : public VibratorPrimitivesBench_Aidl { public: static void DefaultConfig(Benchmark* b) { VibratorPrimitivesBench_Aidl::DefaultConfig(b); SlowBenchConfig(b); } }; BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionDelayMax, { int32_t ms = 0; for (auto _ : state) { mVibrator->getCompositionDelayMax(&ms); if (shouldSkipWithError(state, mVibrator->getCompositionDelayMax(&ms))) { return; } } }); Loading @@ -534,14 +753,14 @@ BENCHMARK_WRAPPER(VibratorBench_Aidl, getCompositionSizeMax, { int32_t size = 0; for (auto _ : state) { mVibrator->getCompositionSizeMax(&size); if (shouldSkipWithError(state, mVibrator->getCompositionSizeMax(&size))) { return; } } }); BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) { state.SkipWithMessage("compose effects unavailable"); return; } Loading @@ -549,22 +768,20 @@ BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, getPrimitiveDuration, { auto primitive = getPrimitive(state); int32_t ms = 0; std::vector<Aidl::CompositePrimitive> supported; mVibrator->getSupportedPrimitives(&supported); if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) { state.SkipWithMessage("supported primitives unavailable"); if (!isPrimitiveSupported(primitive)) { state.SkipWithMessage("primitive unsupported"); return; } for (auto _ : state) { mVibrator->getPrimitiveDuration(primitive, &ms); if (shouldSkipWithError(state, mVibrator->getPrimitiveDuration(primitive, &ms))) { return; } } }); BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, { int32_t capabilities = 0; mVibrator->getCapabilities(&capabilities); if ((capabilities & Aidl::IVibrator::CAP_COMPOSE_EFFECTS) == 0) { BENCHMARK_WRAPPER(SlowVibratorPrimitivesBench_Aidl, compose, { if (!hasCapabilities(Aidl::IVibrator::CAP_COMPOSE_EFFECTS)) { state.SkipWithMessage("compose effects unavailable"); return; } Loading @@ -574,22 +791,33 @@ BENCHMARK_WRAPPER(VibratorPrimitivesBench_Aidl, compose, { effect.scale = 1.0f; effect.delayMs = 0; std::vector<Aidl::CompositePrimitive> supported; mVibrator->getSupportedPrimitives(&supported); if (std::find(supported.begin(), supported.end(), effect.primitive) == supported.end()) { state.SkipWithMessage("supported primitives unavailable"); if (effect.primitive == Aidl::CompositePrimitive::NOOP) { state.SkipWithMessage("skipping primitive NOOP"); return; } if (!isPrimitiveSupported(effect.primitive)) { state.SkipWithMessage("primitive unsupported"); return; } auto cb = new HalCallback(); std::vector<Aidl::CompositeEffect> effects; effects.push_back(effect); for (auto _ : state) { state.ResumeTiming(); mVibrator->compose(effects, cb); auto cb = new HalCallback(); // Test if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) { return; } // Cleanup state.PauseTiming(); mVibrator->off(); if (shouldSkipWithError(state, mVibrator->off())) { return; } cb->waitForComplete(); state.ResumeTiming(); } }); Loading