Add Chirp APIs for PWLE sequence creation
Add the necessary Chirp APIs required to allow for piecewise-linear
equation sequencing of haptic waveforms. These APIs will allow
developers to create a fully customizable sequence of haptics waveforms
for playback.
Bug: 162859057
Test: verify pwle sequences can be created and played using idlcli
command. Also verify using atest.
Change-Id: I7fec224b7090e482bbcd1c94a3799ec232cc547f
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 2540d0b..a9d1ed5 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -15,7 +15,6 @@
*/
#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>
@@ -29,13 +28,17 @@
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(),
@@ -44,32 +47,32 @@
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),
+ 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),
+ 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()};
+ android::enum_range<CompositePrimitive>().begin(),
+ android::enum_range<CompositePrimitive>().end()};
const std::vector<CompositePrimitive> kOptionalPrimitives = {
- CompositePrimitive::THUD,
- CompositePrimitive::SPIN,
+ 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),
+ 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) {}
+ CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
Status onComplete() override {
mCallback();
return Status::ok();
@@ -109,6 +112,89 @@
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);
@@ -116,12 +202,13 @@
}
TEST_P(VibratorAidl, OnWithCallback) {
- if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return;
+ 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(); });
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
uint32_t durationMs = 250;
std::chrono::milliseconds timeout{durationMs * 2};
EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
@@ -142,7 +229,7 @@
for (Effect effect : kEffects) {
bool isEffectSupported =
- std::find(supported.begin(), supported.end(), effect) != supported.end();
+ std::find(supported.begin(), supported.end(), effect) != supported.end();
for (EffectStrength strength : kEffectStrengths) {
int32_t lengthMs = 0;
@@ -154,27 +241,28 @@
usleep(lengthMs * 1000);
} else {
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
}
}
TEST_P(VibratorAidl, ValidateEffectWithCallback) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return;
+ 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();
+ 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(); });
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
int lengthMs = 0;
Status status = vibrator->perform(effect, strength, callback, &lengthMs);
@@ -185,7 +273,8 @@
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
}
- if (!status.isOk()) continue;
+ if (!status.isOk())
+ continue;
std::chrono::milliseconds timeout{lengthMs * 2};
EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
@@ -194,7 +283,8 @@
}
TEST_P(VibratorAidl, ValidateEffectWithCallbackNotSupported) {
- if (capabilities & IVibrator::CAP_PERFORM_CALLBACK) return;
+ if (capabilities & IVibrator::CAP_PERFORM_CALLBACK)
+ return;
for (Effect effect : kEffects) {
for (EffectStrength strength : kEffectStrengths) {
@@ -212,7 +302,7 @@
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
for (Effect effect : kEffects) {
@@ -220,7 +310,7 @@
int32_t lengthMs;
Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
}
@@ -261,7 +351,7 @@
TEST_P(VibratorAidl, ExternalAmplitudeControl) {
const bool supportsExternalAmplitudeControl =
- (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
+ (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
@@ -293,10 +383,10 @@
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
- std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
bool isPrimitiveOptional =
- std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
- kOptionalPrimitives.end();
+ std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
+ kOptionalPrimitives.end();
EXPECT_TRUE(isPrimitiveSupported || isPrimitiveOptional) << toString(primitive);
}
@@ -310,7 +400,7 @@
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
- std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
int32_t duration;
Status status = vibrator->getPrimitiveDuration(primitive, &duration);
@@ -366,7 +456,7 @@
for (auto primitive : kCompositePrimitives) {
bool isPrimitiveSupported =
- std::find(supported.begin(), supported.end(), primitive) != supported.end();
+ std::find(supported.begin(), supported.end(), primitive) != supported.end();
if (!isPrimitiveSupported) {
unsupported.push_back(primitive);
@@ -376,7 +466,7 @@
for (auto primitive : unsupported) {
std::vector<CompositeEffect> composite(1);
- for (auto& effect : composite) {
+ for (auto &effect : composite) {
effect.delayMs = 0;
effect.primitive = primitive;
effect.scale = 1.0f;
@@ -391,7 +481,7 @@
TEST_P(VibratorAidl, ComposeScaleBoundary) {
if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
std::vector<CompositeEffect> composite(1);
- CompositeEffect& effect = composite[0];
+ CompositeEffect &effect = composite[0];
effect.delayMs = 0;
effect.primitive = CompositePrimitive::CLICK;
@@ -478,7 +568,7 @@
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
sp<CompletionCallback> callback =
- new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+ new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
CompositeEffect effect;
std::vector<CompositeEffect> composite;
int32_t durationMs;
@@ -493,16 +583,15 @@
EXPECT_EQ(Status::EX_NONE,
vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
- << toString(primitive);
+ << toString(primitive);
duration = std::chrono::milliseconds(durationMs);
EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
- << toString(primitive);
+ << toString(primitive);
start = high_resolution_clock::now();
- EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency),
- std::future_status::ready)
- << toString(primitive);
+ EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency), std::future_status::ready)
+ << toString(primitive);
end = high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
@@ -519,17 +608,17 @@
for (Effect effect : kEffects) {
bool isEffectSupported =
- std::find(supported.begin(), supported.end(), effect) != supported.end();
+ 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);
+ << toString(effect) << " " << toString(strength);
} else {
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode())
- << toString(effect) << " " << toString(strength);
+ << toString(effect) << " " << toString(strength);
}
}
}
@@ -539,27 +628,253 @@
}
TEST_P(VibratorAidl, GetResonantFrequency) {
- float resonantFrequency;
- Status status = vibrator->getResonantFrequency(&resonantFrequency);
- if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
- ASSERT_NE(resonantFrequency, 0);
- EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
- } else {
- EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
- }
+ getResonantFrequencyHz(vibrator, capabilities);
}
TEST_P(VibratorAidl, GetQFactor) {
float qFactor;
Status status = vibrator->getQFactor(&qFactor);
if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
- ASSERT_NE(qFactor, 0);
+ 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);
@@ -569,7 +884,7 @@
auto managerName = String16(managerAidlNames[i].c_str());
auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
- for (auto& vibratorId : vibratorIds) {
+ for (auto &vibratorId : vibratorIds) {
tuples.push_back(std::make_tuple(i, vibratorId));
}
}
@@ -583,8 +898,8 @@
return tuples;
}
-std::string PrintGeneratedTest(const testing::TestParamInfo<VibratorAidl::ParamType>& info) {
- const auto& [managerIdx, vibratorId] = info.param;
+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);
}
@@ -596,7 +911,7 @@
INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(GenerateVibratorMapping()),
PrintGeneratedTest);
-int main(int argc, char** argv) {
+int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
ProcessState::self()->setThreadPoolMaxThreadCount(1);
ProcessState::self()->startThreadPool();