Fix binder transaction errors on vibrator benchmark tests

Setup binder process thread pool for vibrator HAL benchmark tests to fix
binder transaction errors of the type:

E Vibrator: Failed completion callback: -129

This change also adds checks for HAL results, which will cause them to
fail earlier with a useful error message when the device reaches a bad
state. This should avoid timeout failures for the whole test suite.

Other fixes:

- Fix vibrator.on(ms) tests to use a valid max duration value
  (previously failing with illegal argument);
- Use a smaller fixed # of iterations on tests that iterate on vibrate
  calls, and add wait for vibration to be complete to measure the HAL
  in a more stable state;
- Skip getSupportedAlwaysOnEffects on devices without capability;

Fix: 329239120
Bug: 329899022
Bug: 329203383
Test: atest VibratorHalIntegrationBenchmark
Change-Id: Id541a62745320a601934fd3f176f8ba42b5a7b2d
This commit is contained in:
Lais Andrade 2024-03-12 11:53:00 +00:00
parent 9375782730
commit 59a5d543b0

View file

@ -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;
@ -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;
@ -41,14 +42,28 @@ 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 SetUp(State& /*state*/) override {
android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
android::ProcessState::self()->startThreadPool();
}
void TearDown(State& /*state*/) override {
if (!mVibrator) {
return;
if (mVibrator) {
mVibrator->off();
}
mVibrator->off();
}
static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
@ -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;
@ -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();
}
}
@ -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;
}
}
});
@ -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);
for (auto _ : state) {
mVibrator->setAmplitude(amplitude);
if (shouldSkipWithError(state, mVibrator->on(ms))) {
return;
}
mVibrator->off();
for (auto _ : state) {
if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
return;
}
}
});
using VibratorEffectsBench_V1_0 = VibratorEffectsBench<V1_0::IVibrator, V1_0::Effect>;
@ -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) {
@ -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();
}
});
@ -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, {
@ -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");
@ -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>;
@ -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 {
@ -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();
}
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);
}
private:
std::promise<void> mPromise;
};
BENCHMARK_WRAPPER(VibratorBench_Aidl, on, {
int32_t capabilities = 0;
mVibrator->getCapabilities(&capabilities);
int32_t ms = INT32_MAX;
auto cb = (capabilities & Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
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();
}
});
@ -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);
for (auto _ : state) {
mVibrator->setAmplitude(amplitude);
auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
return;
}
mVibrator->off();
for (auto _ : state) {
if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
return;
}
}
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);
for (auto _ : state) {
mVibrator->setAmplitude(amplitude);
if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
return;
}
mVibrator->setExternalControl(false);
float amplitude = 1.0f;
for (auto _ : state) {
if (shouldSkipWithError(state, mVibrator->setAmplitude(amplitude))) {
return;
}
}
});
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;
}
}
});
@ -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;
}
}
});
@ -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;
}
@ -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;
}
@ -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();
}
});
@ -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;
}
}
});
@ -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;
}
@ -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;
}
@ -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();
}
});