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
diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp
index b96e06d..dd618a5 100644
--- a/vibrator/bench/benchmark.cpp
+++ b/vibrator/bench/benchmark.cpp
@@ -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::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_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 @@
 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 @@
         });
 
         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 @@
 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, 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 @@
 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, 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 @@
         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 @@
         return;
     }
 
-    mVibrator->setExternalControl(true);
+    if (shouldSkipWithError(state, mVibrator->setExternalControl(true))) {
+        return;
+    }
 
     if (!mVibrator->supportsAmplitudeControl()) {
         state.SkipWithMessage("amplitude control unavailable");
@@ -273,10 +341,10 @@
     }
 
     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 @@
 
 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 @@
     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();
-        mVibrator->off();
+
+        // Test
+        if (shouldSkipWithError(state, mVibrator->off())) {
+            return;
+        }
+
+        // Cleanup
+        state.PauseTiming();
+        if (cb) {
+            cb->waitForComplete();
+        }
+        state.ResumeTiming();
     }
 });
 
@@ -327,76 +468,102 @@
     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 @@
     std::vector<Aidl::CompositePrimitive> supportedPrimitives;
 
     for (auto _ : state) {
-        mVibrator->getSupportedPrimitives(&supportedPrimitives);
+        if (shouldSkipWithError(state, mVibrator->getSupportedPrimitives(&supportedPrimitives))) {
+            return;
+        }
     }
 });
 
@@ -427,12 +596,30 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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();
     }
 });