Files
hardware_interfaces/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
Vince Leung 36f70d6ffc Relax timing parameters for vibrator VTS
First we set the start timestamp before we call the compose method.
We'll increase the allowed latency to if the system is under heavy load
then there can be more latencies.

Bug: 184578694
Test: atest
Change-Id: I5c06017ab0242d32b281ff3a0d0dddcb2106de5d
2021-04-14 04:33:20 +00:00

917 lines
34 KiB
C++

/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <android/hardware/vibrator/IVibratorManager.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cmath>
#include <future>
using android::ProcessState;
using android::sp;
using android::String16;
using android::binder::Status;
using android::hardware::vibrator::ActivePwle;
using android::hardware::vibrator::BnVibratorCallback;
using android::hardware::vibrator::Braking;
using android::hardware::vibrator::BrakingPwle;
using android::hardware::vibrator::CompositeEffect;
using android::hardware::vibrator::CompositePrimitive;
using android::hardware::vibrator::Effect;
using android::hardware::vibrator::EffectStrength;
using android::hardware::vibrator::IVibrator;
using android::hardware::vibrator::IVibratorManager;
using android::hardware::vibrator::PrimitivePwle;
using std::chrono::high_resolution_clock;
const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
android::enum_range<Effect>().end()};
const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
android::enum_range<EffectStrength>().end()};
const std::vector<Effect> kInvalidEffects = {
static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
static_cast<Effect>(static_cast<int32_t>(kEffects.back()) + 1),
};
const std::vector<EffectStrength> kInvalidEffectStrengths = {
static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.front()) - 1),
static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.back()) + 1),
};
const std::vector<CompositePrimitive> kCompositePrimitives{
android::enum_range<CompositePrimitive>().begin(),
android::enum_range<CompositePrimitive>().end()};
const std::vector<CompositePrimitive> kOptionalPrimitives = {
CompositePrimitive::THUD,
CompositePrimitive::SPIN,
};
const std::vector<CompositePrimitive> kInvalidPrimitives = {
static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.front()) - 1),
static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
};
class CompletionCallback : public BnVibratorCallback {
public:
CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
Status onComplete() override {
mCallback();
return Status::ok();
}
private:
std::function<void()> mCallback;
};
class VibratorAidl : public testing::TestWithParam<std::tuple<int32_t, int32_t>> {
public:
virtual void SetUp() override {
int32_t managerIdx = std::get<0>(GetParam());
int32_t vibratorId = std::get<1>(GetParam());
auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
if (managerIdx < 0) {
// Testing a unmanaged vibrator, using vibratorId as index from registered HALs
auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
ASSERT_LT(vibratorId, vibratorAidlNames.size());
auto vibratorName = String16(vibratorAidlNames[vibratorId].c_str());
vibrator = android::waitForDeclaredService<IVibrator>(vibratorName);
} else {
// Testing a managed vibrator, using vibratorId to retrieve it from the manager
ASSERT_LT(managerIdx, managerAidlNames.size());
auto managerName = String16(managerAidlNames[managerIdx].c_str());
auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
auto vibratorResult = vibratorManager->getVibrator(vibratorId, &vibrator);
ASSERT_TRUE(vibratorResult.isOk());
}
ASSERT_NE(vibrator, nullptr);
ASSERT_TRUE(vibrator->getCapabilities(&capabilities).isOk());
}
sp<IVibrator> vibrator;
int32_t capabilities;
};
static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
float resonantFrequencyHz;
Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
EXPECT_GT(resonantFrequencyHz, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
return resonantFrequencyHz;
}
static float getFrequencyResolutionHz(sp<IVibrator> vibrator, int32_t capabilities) {
float freqResolutionHz;
Status status = vibrator->getFrequencyResolution(&freqResolutionHz);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
EXPECT_GT(freqResolutionHz, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
return freqResolutionHz;
}
static float getFrequencyMinimumHz(sp<IVibrator> vibrator, int32_t capabilities) {
float freqMinimumHz;
Status status = vibrator->getFrequencyMinimum(&freqMinimumHz);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities);
EXPECT_GT(freqMinimumHz, 0);
EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
return freqMinimumHz;
}
static float getFrequencyMaximumHz(sp<IVibrator> vibrator, int32_t capabilities) {
std::vector<float> bandwidthAmplitudeMap;
Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
float freqMaximumHz =
(bandwidthAmplitudeMap.size() * getFrequencyResolutionHz(vibrator, capabilities)) +
getFrequencyMinimumHz(vibrator, capabilities);
return freqMaximumHz;
}
static float getAmplitudeMin() {
return 0.0;
}
static float getAmplitudeMax() {
return 1.0;
}
static ActivePwle composeValidActivePwle(sp<IVibrator> vibrator, int32_t capabilities) {
float frequencyHz;
if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
frequencyHz = getResonantFrequencyHz(vibrator, capabilities);
} else if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
frequencyHz = getFrequencyMinimumHz(vibrator, capabilities);
} else {
frequencyHz = 150.0; // default value commonly used
}
ActivePwle active;
active.startAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2;
active.startFrequency = frequencyHz;
active.endAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2;
active.endFrequency = frequencyHz;
active.duration = 1000;
return active;
}
TEST_P(VibratorAidl, OnThenOffBeforeTimeout) {
EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
sleep(1);
EXPECT_TRUE(vibrator->off().isOk());
}
TEST_P(VibratorAidl, OnWithCallback) {
if (!(capabilities & IVibrator::CAP_ON_CALLBACK))
return;
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
uint32_t durationMs = 250;
std::chrono::milliseconds timeout{durationMs * 2};
EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
EXPECT_TRUE(vibrator->off().isOk());
}
TEST_P(VibratorAidl, OnCallbackNotSupported) {
if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
sp<CompletionCallback> callback = new CompletionCallback([] {});
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode());
}
}
TEST_P(VibratorAidl, ValidateEffect) {
std::vector<Effect> supported;
ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
for (Effect effect : kEffects) {
bool isEffectSupported =
std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
int32_t lengthMs = 0;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
if (isEffectSupported) {
EXPECT_TRUE(status.isOk()) << toString(effect) << " " << toString(strength);
EXPECT_GT(lengthMs, 0);
usleep(lengthMs * 1000);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
<< toString(effect) << " " << toString(strength);
}
}
}
}
TEST_P(VibratorAidl, ValidateEffectWithCallback) {
if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK))
return;
std::vector<Effect> supported;
ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
for (Effect effect : kEffects) {
bool isEffectSupported =
std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
int lengthMs = 0;
Status status = vibrator->perform(effect, strength, callback, &lengthMs);
if (isEffectSupported) {
EXPECT_TRUE(status.isOk());
EXPECT_GT(lengthMs, 0);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
if (!status.isOk())
continue;
std::chrono::milliseconds timeout{lengthMs * 2};
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
}
}
}
TEST_P(VibratorAidl, ValidateEffectWithCallbackNotSupported) {
if (capabilities & IVibrator::CAP_PERFORM_CALLBACK)
return;
for (Effect effect : kEffects) {
for (EffectStrength strength : kEffectStrengths) {
sp<CompletionCallback> callback = new CompletionCallback([] {});
int lengthMs;
Status status = vibrator->perform(effect, strength, callback, &lengthMs);
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
}
}
}
TEST_P(VibratorAidl, InvalidEffectsUnsupported) {
for (Effect effect : kInvalidEffects) {
for (EffectStrength strength : kEffectStrengths) {
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
<< toString(effect) << " " << toString(strength);
}
}
for (Effect effect : kEffects) {
for (EffectStrength strength : kInvalidEffectStrengths) {
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
<< toString(effect) << " " << toString(strength);
}
}
}
TEST_P(VibratorAidl, ChangeVibrationAmplitude) {
if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.1f).exceptionCode());
EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.5f).exceptionCode());
sleep(1);
EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(1.0f).exceptionCode());
sleep(1);
}
}
TEST_P(VibratorAidl, AmplitudeOutsideRangeFails) {
if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(-1).exceptionCode());
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(0).exceptionCode());
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(1.1).exceptionCode());
}
}
TEST_P(VibratorAidl, AmplitudeReturnsUnsupportedMatchingCapabilities) {
if ((capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->setAmplitude(1).exceptionCode());
}
}
TEST_P(VibratorAidl, ChangeVibrationExternalControl) {
if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
sleep(1);
EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
sleep(1);
}
}
TEST_P(VibratorAidl, ExternalAmplitudeControl) {
const bool supportsExternalAmplitudeControl =
(capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
Status amplitudeStatus = vibrator->setAmplitude(0.5);
if (supportsExternalAmplitudeControl) {
EXPECT_TRUE(amplitudeStatus.isOk());
} else {
EXPECT_EQ(amplitudeStatus.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
} else {
EXPECT_FALSE(supportsExternalAmplitudeControl);
}
}
TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) {
if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
vibrator->setExternalControl(true).exceptionCode());
}
}
TEST_P(VibratorAidl, GetSupportedPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
EXPECT_EQ(Status::EX_NONE, vibrator->getSupportedPrimitives(&supported).exceptionCode());
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
std::find(supported.begin(), supported.end(), primitive) != supported.end();
bool isPrimitiveOptional =
std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
kOptionalPrimitives.end();
EXPECT_TRUE(isPrimitiveSupported || isPrimitiveOptional) << toString(primitive);
}
}
}
TEST_P(VibratorAidl, GetPrimitiveDuration) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
std::find(supported.begin(), supported.end(), primitive) != supported.end();
int32_t duration;
Status status = vibrator->getPrimitiveDuration(primitive, &duration);
if (isPrimitiveSupported) {
EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
} else {
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
}
}
}
}
TEST_P(VibratorAidl, ComposeValidPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
int32_t maxDelay, maxSize;
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<CompositeEffect> composite;
for (auto primitive : supported) {
CompositeEffect effect;
effect.delayMs = std::rand() % (maxDelay + 1);
effect.primitive = primitive;
effect.scale = static_cast<float>(std::rand()) / RAND_MAX;
composite.emplace_back(effect);
if (composite.size() == maxSize) {
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
composite.clear();
vibrator->off();
}
}
if (composite.size() != 0) {
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
vibrator->off();
}
}
}
TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
auto unsupported = kInvalidPrimitives;
std::vector<CompositePrimitive> supported;
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);
}
}
for (auto primitive : unsupported) {
std::vector<CompositeEffect> composite(1);
for (auto &effect : composite) {
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
}
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
vibrator->compose(composite, nullptr).exceptionCode());
vibrator->off();
}
}
}
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();
}
}
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();
}
}
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();
}
}
TEST_P(VibratorAidl, ComposeCallback) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositePrimitive> supported;
ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
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);
EXPECT_EQ(completionFuture.wait_for(duration * 2), 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);
}
}
}
TEST_P(VibratorAidl, AlwaysOn) {
if (capabilities & IVibrator::CAP_ALWAYS_ON_CONTROL) {
std::vector<Effect> supported;
ASSERT_TRUE(vibrator->getSupportedAlwaysOnEffects(&supported).isOk());
for (Effect effect : kEffects) {
bool isEffectSupported =
std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
Status status = vibrator->alwaysOnEnable(0, effect, strength);
if (isEffectSupported) {
EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
<< toString(effect) << " " << toString(strength);
} else {
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode())
<< toString(effect) << " " << toString(strength);
}
}
}
EXPECT_EQ(Status::EX_NONE, vibrator->alwaysOnDisable(0).exceptionCode());
}
}
TEST_P(VibratorAidl, GetResonantFrequency) {
getResonantFrequencyHz(vibrator, capabilities);
}
TEST_P(VibratorAidl, GetQFactor) {
float qFactor;
Status status = vibrator->getQFactor(&qFactor);
if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
ASSERT_GT(qFactor, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
}
TEST_P(VibratorAidl, GetFrequencyResolution) {
getFrequencyResolutionHz(vibrator, capabilities);
}
TEST_P(VibratorAidl, GetFrequencyMinimum) {
getFrequencyMinimumHz(vibrator, capabilities);
}
TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) {
std::vector<float> bandwidthAmplitudeMap;
Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
ASSERT_FALSE(bandwidthAmplitudeMap.empty());
int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) -
getFrequencyMinimumHz(vibrator, capabilities)) /
getFrequencyResolutionHz(vibrator, capabilities);
ASSERT_GT(bandwidthAmplitudeMap.size(), minMapSize);
for (float e : bandwidthAmplitudeMap) {
ASSERT_GE(e, 0.0);
ASSERT_LE(e, 1.0);
}
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
}
TEST_P(VibratorAidl, GetPwlePrimitiveDurationMax) {
int32_t durationMs;
Status status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
ASSERT_NE(durationMs, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
}
TEST_P(VibratorAidl, GetPwleCompositionSizeMax) {
int32_t maxSize;
Status status = vibrator->getPwleCompositionSizeMax(&maxSize);
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
ASSERT_NE(maxSize, 0);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
}
TEST_P(VibratorAidl, GetSupportedBraking) {
std::vector<Braking> supported;
Status status = vibrator->getSupportedBraking(&supported);
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
bool isDefaultNoneSupported =
std::find(supported.begin(), supported.end(), Braking::NONE) != supported.end();
ASSERT_TRUE(isDefaultNoneSupported);
EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
}
TEST_P(VibratorAidl, ComposeValidPwle) {
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
std::vector<Braking> supported;
ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
bool isClabSupported =
std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
BrakingPwle braking;
braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
braking.duration = 100;
std::vector<PrimitivePwle> pwleQueue;
PrimitivePwle pwle;
pwle = active;
pwleQueue.emplace_back(std::move(pwle));
pwle = braking;
pwleQueue.emplace_back(std::move(pwle));
pwle = active;
pwleQueue.emplace_back(std::move(pwle));
EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
vibrator->off();
}
}
TEST_P(VibratorAidl, ComposeValidPwleWithCallback) {
if (!((capabilities & IVibrator::CAP_ON_CALLBACK) &&
(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS)))
return;
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
uint32_t durationMs = 2100; // Sum of 2 active and 1 braking below
std::chrono::milliseconds timeout{durationMs * 2};
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
std::vector<Braking> supported;
ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
bool isClabSupported =
std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
BrakingPwle braking;
braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
braking.duration = 100;
std::vector<PrimitivePwle> pwleQueue;
PrimitivePwle pwle;
pwle = active;
pwleQueue.emplace_back(std::move(pwle));
pwle = braking;
pwleQueue.emplace_back(std::move(pwle));
pwle = active;
pwleQueue.emplace_back(std::move(pwle));
EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk());
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
EXPECT_TRUE(vibrator->off().isOk());
}
TEST_P(VibratorAidl, ComposePwleSegmentBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
std::vector<PrimitivePwle> pwleQueue;
// test empty queue
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
vibrator->off();
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
PrimitivePwle pwle;
pwle = active;
int segmentCountMax;
vibrator->getPwleCompositionSizeMax(&segmentCountMax);
// Create PWLE queue with more segments than allowed
for (int i = 0; i < segmentCountMax + 10; i++) {
pwleQueue.emplace_back(std::move(pwle));
}
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
vibrator->off();
}
}
TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
active.startAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed
active.endAmplitude = getAmplitudeMax() + 1.0; // Amplitude greater than allowed
std::vector<PrimitivePwle> pwleQueueGreater;
PrimitivePwle pwle;
pwle = active;
pwleQueueGreater.emplace_back(std::move(pwle));
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
vibrator->off();
active.startAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed
active.endAmplitude = getAmplitudeMin() - 1.0; // Amplitude less than allowed
std::vector<PrimitivePwle> pwleQueueLess;
pwle = active;
pwleQueueLess.emplace_back(std::move(pwle));
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
vibrator->off();
}
}
TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) {
if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) &&
(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities);
float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities);
float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities);
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
active.startFrequency =
freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
active.endFrequency = freqMaximumHz + freqResolutionHz; // Frequency greater than allowed
std::vector<PrimitivePwle> pwleQueueGreater;
PrimitivePwle pwle;
pwle = active;
pwleQueueGreater.emplace_back(std::move(pwle));
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
vibrator->off();
active.startFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed
active.endFrequency = freqMinimumHz - freqResolutionHz; // Frequency less than allowed
std::vector<PrimitivePwle> pwleQueueLess;
pwle = active;
pwleQueueLess.emplace_back(std::move(pwle));
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
vibrator->off();
}
}
TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
ActivePwle active = composeValidActivePwle(vibrator, capabilities);
int segmentDurationMaxMs;
vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
active.duration = segmentDurationMaxMs + 10; // Segment duration greater than allowed
std::vector<PrimitivePwle> pwleQueue;
PrimitivePwle pwle;
pwle = active;
pwleQueue.emplace_back(std::move(pwle));
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
vibrator->off();
}
}
std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
std::vector<std::tuple<int32_t, int32_t>> tuples;
auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
std::vector<int32_t> vibratorIds;
for (int i = 0; i < managerAidlNames.size(); i++) {
auto managerName = String16(managerAidlNames[i].c_str());
auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
for (auto &vibratorId : vibratorIds) {
tuples.push_back(std::make_tuple(i, vibratorId));
}
}
}
auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
for (int i = 0; i < vibratorAidlNames.size(); i++) {
tuples.push_back(std::make_tuple(-1, i));
}
return tuples;
}
std::string PrintGeneratedTest(const testing::TestParamInfo<VibratorAidl::ParamType> &info) {
const auto &[managerIdx, vibratorId] = info.param;
if (managerIdx < 0) {
return std::string("TOP_LEVEL_VIBRATOR_") + std::to_string(vibratorId);
}
return std::string("MANAGER_") + std::to_string(managerIdx) + "_VIBRATOR_ID_" +
std::to_string(vibratorId);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl);
INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(GenerateVibratorMapping()),
PrintGeneratedTest);
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
ProcessState::self()->setThreadPoolMaxThreadCount(1);
ProcessState::self()->startThreadPool();
return RUN_ALL_TESTS();
}