Fix vibrator compose VTS tests

Add TearDown method to reset the vibrator state between tests to avoid
illegal state errors caused by unrelated tests.

Add calls to vibrator->off between vibrator->compose invocations within
the same test, so calls are tested individually.

Test runs with this change on failing targets:

Bug: 323087313
Test: atest VtsHalVibratorTargetTest
Change-Id: I1e9aa243da07040b33df2474977fc8becac440a5
This commit is contained in:
Lais Andrade
2024-02-09 12:42:09 +00:00
parent 74e851c0b9
commit 38d054e4ae

View File

@@ -109,6 +109,11 @@ class VibratorAidl : public testing::TestWithParam<std::tuple<int32_t, int32_t>>
ASSERT_TRUE(vibrator->getCapabilities(&capabilities).isOk());
}
virtual void TearDown() override {
// Reset vibrator state between tests.
EXPECT_TRUE(vibrator->off().isOk());
}
sp<IVibrator> vibrator;
int32_t capabilities;
};
@@ -429,189 +434,196 @@ TEST_P(VibratorAidl, GetPrimitiveDuration) {
}
TEST_P(VibratorAidl, ComposeValidPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
int32_t maxDelay, maxSize;
if (!(capabilities & IVibrator::CAP_COMPOSE_EFFECTS)) {
GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
}
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
std::vector<CompositePrimitive> supported;
int32_t maxDelay, maxSize;
std::vector<CompositeEffect> composite;
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
for (auto primitive : supported) {
CompositeEffect effect;
std::vector<CompositeEffect> composite;
effect.delayMs = std::rand() % (maxDelay + 1);
effect.primitive = primitive;
effect.scale = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
composite.emplace_back(effect);
for (auto primitive : supported) {
CompositeEffect effect;
if (composite.size() == maxSize) {
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
composite.clear();
vibrator->off();
}
effect.delayMs = std::rand() % (maxDelay + 1);
effect.primitive = primitive;
effect.scale = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
composite.emplace_back(effect);
if (composite.size() == maxSize) {
break;
}
}
if (composite.size() != 0) {
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
vibrator->off();
}
if (composite.size() != 0) {
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
EXPECT_TRUE(vibrator->off().isOk());
}
}
TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
auto unsupported = kInvalidPrimitives;
std::vector<CompositePrimitive> supported;
if (!(capabilities & IVibrator::CAP_COMPOSE_EFFECTS)) {
GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
}
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
auto unsupported = kInvalidPrimitives;
std::vector<CompositePrimitive> supported;
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
std::find(supported.begin(), supported.end(), primitive) != supported.end();
if (!isPrimitiveSupported) {
unsupported.push_back(primitive);
}
if (!isPrimitiveSupported) {
unsupported.push_back(primitive);
}
}
for (auto primitive : unsupported) {
std::vector<CompositeEffect> composite(1);
for (auto primitive : unsupported) {
std::vector<CompositeEffect> composite(1);
for (auto &effect : composite) {
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
}
Status status = vibrator->compose(composite, nullptr);
EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
vibrator->off();
for (auto& effect : composite) {
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
}
Status status = vibrator->compose(composite, nullptr);
EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
}
}
TEST_P(VibratorAidl, ComposeScaleBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositeEffect> composite(1);
CompositeEffect &effect = composite[0];
effect.delayMs = 0;
effect.primitive = CompositePrimitive::CLICK;
effect.scale = std::nextafter(0.0f, -1.0f);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->compose(composite, nullptr).exceptionCode());
effect.scale = 0.0f;
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
effect.scale = 1.0f;
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
effect.scale = std::nextafter(1.0f, 2.0f);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->compose(composite, nullptr).exceptionCode());
vibrator->off();
if (!(capabilities & IVibrator::CAP_COMPOSE_EFFECTS)) {
GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
}
std::vector<CompositeEffect> composite(1);
CompositeEffect& effect = composite[0];
effect.delayMs = 0;
effect.primitive = CompositePrimitive::CLICK;
effect.scale = std::nextafter(0.0f, -1.0f);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
effect.scale = 0.0f;
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
EXPECT_TRUE(vibrator->off().isOk());
effect.scale = 1.0f;
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
EXPECT_TRUE(vibrator->off().isOk());
effect.scale = std::nextafter(1.0f, 2.0f);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
}
TEST_P(VibratorAidl, ComposeDelayBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
int32_t maxDelay;
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
std::vector<CompositeEffect> composite(1);
CompositeEffect effect;
effect.delayMs = 1;
effect.primitive = CompositePrimitive::CLICK;
effect.scale = 1.0f;
std::fill(composite.begin(), composite.end(), effect);
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
effect.delayMs = maxDelay + 1;
std::fill(composite.begin(), composite.end(), effect);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->compose(composite, nullptr).exceptionCode());
vibrator->off();
if (!(capabilities & IVibrator::CAP_COMPOSE_EFFECTS)) {
GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
}
int32_t maxDelay;
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
std::vector<CompositeEffect> composite(1);
CompositeEffect effect;
effect.delayMs = 1;
effect.primitive = CompositePrimitive::CLICK;
effect.scale = 1.0f;
std::fill(composite.begin(), composite.end(), effect);
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
EXPECT_TRUE(vibrator->off().isOk());
effect.delayMs = maxDelay + 1;
std::fill(composite.begin(), composite.end(), effect);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
}
TEST_P(VibratorAidl, ComposeSizeBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
int32_t maxSize;
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
std::vector<CompositeEffect> composite(maxSize);
CompositeEffect effect;
effect.delayMs = 1;
effect.primitive = CompositePrimitive::CLICK;
effect.scale = 1.0f;
std::fill(composite.begin(), composite.end(), effect);
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
composite.emplace_back(effect);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->compose(composite, nullptr).exceptionCode());
vibrator->off();
if (!(capabilities & IVibrator::CAP_COMPOSE_EFFECTS)) {
GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
}
int32_t maxSize;
EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
std::vector<CompositeEffect> composite(maxSize);
CompositeEffect effect;
effect.delayMs = 1;
effect.primitive = CompositePrimitive::CLICK;
effect.scale = 1.0f;
std::fill(composite.begin(), composite.end(), effect);
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
EXPECT_TRUE(vibrator->off().isOk());
composite.emplace_back(effect);
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
}
TEST_P(VibratorAidl, ComposeCallback) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
if (!(capabilities & IVibrator::CAP_COMPOSE_EFFECTS)) {
GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
}
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
std::vector<CompositePrimitive> supported;
for (auto primitive : supported) {
if (primitive == CompositePrimitive::NOOP) {
continue;
}
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
CompositeEffect effect;
std::vector<CompositeEffect> composite;
int32_t durationMs;
std::chrono::milliseconds duration;
std::chrono::time_point<high_resolution_clock> start, end;
std::chrono::milliseconds elapsed;
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
composite.emplace_back(effect);
EXPECT_EQ(Status::EX_NONE,
vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
<< toString(primitive);
duration = std::chrono::milliseconds(durationMs);
start = high_resolution_clock::now();
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
<< toString(primitive);
// TODO(b/261130361): Investigate why latency from driver and hardware will cause test
// to fail when wait duration is ~40ms or less.
EXPECT_EQ(completionFuture.wait_for(duration + std::chrono::milliseconds(50)),
std::future_status::ready)
<< toString(primitive);
end = high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive);
for (auto primitive : supported) {
if (primitive == CompositePrimitive::NOOP) {
continue;
}
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
CompositeEffect effect;
std::vector<CompositeEffect> composite;
int32_t durationMs;
std::chrono::milliseconds duration;
std::chrono::time_point<high_resolution_clock> start, end;
std::chrono::milliseconds elapsed;
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
composite.emplace_back(effect);
EXPECT_EQ(Status::EX_NONE,
vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
<< toString(primitive);
duration = std::chrono::milliseconds(durationMs);
start = high_resolution_clock::now();
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
<< toString(primitive);
// TODO(b/261130361): Investigate why latency from driver and hardware will cause test
// to fail when wait duration is ~40ms or less.
EXPECT_EQ(completionFuture.wait_for(duration + std::chrono::milliseconds(50)),
std::future_status::ready)
<< toString(primitive);
end = high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive);
EXPECT_TRUE(vibrator->off().isOk());
}
}