Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 63e4c30a authored by Lais Andrade's avatar Lais Andrade
Browse files

Fixes in power benchmarks

- Add support check before running PowerHalAidlBenchmarks for setBoost
  and setMode, to avoid testing unsupported values and getting the HAL
  in a bad state.
- Introduce loop breaks when a binder call fails, since SkipWithError
  is not enough to end the loop early and might cause test timeout if
  we try to interact with a HAL in a bad state.
- Move PauseTiming/ResumeTimings to wrap one-way call delays only, as
  this API is expensive and should be used sparsely (and it's needed
  there to avoid filling up the one-way binder queue).
- Make sure we close all sessions in createHintSession tests.
- Use ndk::enum_range in AIDL enums to cover all available boost and
  mode values.

Fix: 351008375
Flag: EXEMPT test only
Change-Id: I6b277d60767f5928e397765b7dcabd709c4f8953
Test: libpowermanager_benchmarks
parent c09f9fa2
Loading
Loading
Loading
Loading
+58 −16
Original line number Diff line number Diff line
@@ -40,10 +40,10 @@ using namespace android;
using namespace std::chrono_literals;

// Values from Boost.aidl and Mode.aidl.
static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(*ndk::enum_range<Boost>().begin());
static constexpr int64_t LAST_BOOST = static_cast<int64_t>(*(ndk::enum_range<Boost>().end()-1));
static constexpr int64_t FIRST_MODE = static_cast<int64_t>(*ndk::enum_range<Mode>().begin());
static constexpr int64_t LAST_MODE = static_cast<int64_t>(*(ndk::enum_range<Mode>().end()-1));

class DurationWrapper : public WorkDuration {
public:
@@ -81,16 +81,19 @@ static void runBenchmark(benchmark::State& state, microseconds delay, R (IPower:
        return;
    }

    while (state.KeepRunning()) {
    for (auto _ : state) {
        ret = (*hal.*fn)(std::forward<Args1>(args1)...);
        state.PauseTiming();
        if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
        if (!ret.isOk()) {
            state.SkipWithError(ret.getDescription().c_str());
            break;
        }
        if (delay > 0us) {
            state.PauseTiming();
            testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
        }
            state.ResumeTiming();
        }
    }
}

template <class R, class... Args0, class... Args1>
static void runSessionBenchmark(benchmark::State& state, R (IPowerHintSession::*fn)(Args0...),
@@ -123,14 +126,15 @@ static void runSessionBenchmark(benchmark::State& state, R (IPowerHintSession::*
        return;
    }

    while (state.KeepRunning()) {
    for (auto _ : state) {
        ret = (*session.*fn)(std::forward<Args1>(args1)...);
        if (!ret.isOk()) {
            state.SkipWithError(ret.getDescription().c_str());
            break;
        }
        state.PauseTiming();
        if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
        if (ONEWAY_API_DELAY > 0us) {
        testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY)
                                .count());
        }
        state.ResumeTiming();
    }
    session->close();
@@ -150,11 +154,41 @@ static void BM_PowerHalAidlBenchmarks_isModeSupported(benchmark::State& state) {

static void BM_PowerHalAidlBenchmarks_setBoost(benchmark::State& state) {
    Boost boost = static_cast<Boost>(state.range(0));
    bool isSupported;
    std::shared_ptr<IPower> hal = PowerHalLoader::loadAidl();

    if (hal == nullptr) {
        ALOGV("Power HAL not available, skipping test...");
        state.SkipWithMessage("Power HAL unavailable");
        return;
    }

    ndk::ScopedAStatus ret = hal->isBoostSupported(boost, &isSupported);
    if (!ret.isOk() || !isSupported) {
        state.SkipWithMessage("operation unsupported");
        return;
    }

    runBenchmark(state, ONEWAY_API_DELAY, &IPower::setBoost, boost, 1);
}

static void BM_PowerHalAidlBenchmarks_setMode(benchmark::State& state) {
    Mode mode = static_cast<Mode>(state.range(0));
    bool isSupported;
    std::shared_ptr<IPower> hal = PowerHalLoader::loadAidl();

    if (hal == nullptr) {
        ALOGV("Power HAL not available, skipping test...");
        state.SkipWithMessage("Power HAL unavailable");
        return;
    }

    ndk::ScopedAStatus ret = hal->isModeSupported(mode, &isSupported);
    if (!ret.isOk() || !isSupported) {
        state.SkipWithMessage("operation unsupported");
        return;
    }

    runBenchmark(state, ONEWAY_API_DELAY, &IPower::setMode, mode, false);
}

@@ -178,12 +212,20 @@ static void BM_PowerHalAidlBenchmarks_createHintSession(benchmark::State& state)
        ALOGV("Power HAL does not support this operation, skipping test...");
        state.SkipWithMessage("operation unsupported");
        return;
    } else if (!ret.isOk()) {
        state.SkipWithError(ret.getDescription().c_str());
        return;
    } else {
        appSession->close();
    }

    while (state.KeepRunning()) {
    for (auto _ : state) {
        ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession);
        if (!ret.isOk()) {
            state.SkipWithError(ret.getDescription().c_str());
            break;
        }
        state.PauseTiming();
        if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
        appSession->close();
        state.ResumeTiming();
    }
+39 −18
Original line number Diff line number Diff line
@@ -19,9 +19,9 @@
#include <aidl/android/hardware/power/Boost.h>
#include <aidl/android/hardware/power/Mode.h>
#include <benchmark/benchmark.h>
#include <chrono>
#include <powermanager/PowerHalController.h>
#include <testUtil.h>
#include <chrono>

using aidl::android::hardware::power::Boost;
using aidl::android::hardware::power::Mode;
@@ -32,10 +32,10 @@ using namespace android;
using namespace std::chrono_literals;

// Values from Boost.aidl and Mode.aidl.
static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(*ndk::enum_range<Boost>().begin());
static constexpr int64_t LAST_BOOST = static_cast<int64_t>(*(ndk::enum_range<Boost>().end()-1));
static constexpr int64_t FIRST_MODE = static_cast<int64_t>(*ndk::enum_range<Mode>().begin());
static constexpr int64_t LAST_MODE = static_cast<int64_t>(*(ndk::enum_range<Mode>().end()-1));

// Delay between oneway method calls to avoid overflowing the binder buffers.
static constexpr std::chrono::microseconds ONEWAY_API_DELAY = 100us;
@@ -43,11 +43,27 @@ static constexpr std::chrono::microseconds ONEWAY_API_DELAY = 100us;
template <typename T, class... Args0, class... Args1>
static void runBenchmark(benchmark::State& state, HalResult<T> (PowerHalController::*fn)(Args0...),
                         Args1&&... args1) {
    while (state.KeepRunning()) {
        PowerHalController controller;
    PowerHalController initController;
    HalResult<T> result = (initController.*fn)(std::forward<Args1>(args1)...);
    if (result.isFailed()) {
        state.SkipWithError(result.errorMessage());
        return;
    } else if (result.isUnsupported()) {
        ALOGV("Power HAL does not support this operation, skipping test...");
        state.SkipWithMessage("operation unsupported");
        return;
    }

    for (auto _ : state) {
        PowerHalController controller; // new controller to avoid caching
        HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
        if (ret.isFailed()) {
            state.SkipWithError(ret.errorMessage());
            break;
        }
        state.PauseTiming();
        if (ret.isFailed()) state.SkipWithError("Power HAL request failed");
        testDelaySpin(
                std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY).count());
        state.ResumeTiming();
    }
}
@@ -57,22 +73,27 @@ static void runCachedBenchmark(benchmark::State& state,
                               HalResult<T> (PowerHalController::*fn)(Args0...), Args1&&... args1) {
    PowerHalController controller;
    // First call out of test, to cache HAL service and isSupported result.
    (controller.*fn)(std::forward<Args1>(args1)...);
    HalResult<T> result = (controller.*fn)(std::forward<Args1>(args1)...);
    if (result.isFailed()) {
        state.SkipWithError(result.errorMessage());
        return;
    } else if (result.isUnsupported()) {
        ALOGV("Power HAL does not support this operation, skipping test...");
        state.SkipWithMessage("operation unsupported");
        return;
    }

    while (state.KeepRunning()) {
    for (auto _ : state) {
        HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
        state.PauseTiming();
        if (ret.isFailed()) {
            state.SkipWithError("Power HAL request failed");
            state.SkipWithError(ret.errorMessage());
            break;
        }
        testDelaySpin(
                std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY).count());
        state.ResumeTiming();
    }
}

static void BM_PowerHalControllerBenchmarks_init(benchmark::State& state) {
    while (state.KeepRunning()) {
    for (auto _ : state) {
        PowerHalController controller;
        controller.init();
    }
@@ -90,12 +111,12 @@ static void BM_PowerHalControllerBenchmarks_initCached(benchmark::State& state)

static void BM_PowerHalControllerBenchmarks_setBoost(benchmark::State& state) {
    Boost boost = static_cast<Boost>(state.range(0));
    runBenchmark(state, &PowerHalController::setBoost, boost, 0);
    runBenchmark(state, &PowerHalController::setBoost, boost, 1);
}

static void BM_PowerHalControllerBenchmarks_setBoostCached(benchmark::State& state) {
    Boost boost = static_cast<Boost>(state.range(0));
    runCachedBenchmark(state, &PowerHalController::setBoost, boost, 0);
    runCachedBenchmark(state, &PowerHalController::setBoost, boost, 1);
}

static void BM_PowerHalControllerBenchmarks_setMode(benchmark::State& state) {
+7 −4
Original line number Diff line number Diff line
@@ -54,16 +54,19 @@ static void runBenchmark(benchmark::State& state, microseconds delay, Return<R>
        return;
    }

    while (state.KeepRunning()) {
    for (auto _ : state) {
        Return<R> ret = (*hal.*fn)(std::forward<Args1>(args1)...);
        state.PauseTiming();
        if (!ret.isOk()) state.SkipWithError(ret.description().c_str());
        if (!ret.isOk()) {
            state.SkipWithError(ret.description().c_str());
            break;
        }
        if (delay > 0us) {
            state.PauseTiming();
            testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
        }
            state.ResumeTiming();
        }
    }
}

static void BM_PowerHalHidlBenchmarks_setFeature(benchmark::State& state) {
    runBenchmark(state, 0us, &IPower1_0::setFeature, Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE,