123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- /*
- * Copyright (C) 2022 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/android/hardware/vibrator/BnVibratorCallback.h>
- #include <android-base/logging.h>
- #include <gmock/gmock.h>
- #include <gtest/gtest.h>
- #include <linux/input.h>
- #include <linux/uinput.h>
- #include <future>
- #include "Vibrator.h"
- #include "mocks.h"
- #include "types.h"
- #include "utils.h"
- namespace aidl {
- namespace android {
- namespace hardware {
- namespace vibrator {
- using ::testing::_;
- using ::testing::AnyNumber;
- using ::testing::Assign;
- using ::testing::AtLeast;
- using ::testing::AtMost;
- using ::testing::Combine;
- using ::testing::DoAll;
- using ::testing::DoDefault;
- using ::testing::Exactly;
- using ::testing::Expectation;
- using ::testing::ExpectationSet;
- using ::testing::Ge;
- using ::testing::Mock;
- using ::testing::MockFunction;
- using ::testing::Range;
- using ::testing::Return;
- using ::testing::Sequence;
- using ::testing::SetArgPointee;
- using ::testing::SetArgReferee;
- using ::testing::Test;
- using ::testing::TestParamInfo;
- using ::testing::ValuesIn;
- using ::testing::WithParamInterface;
- // Forward Declarations
- static EffectQueue Queue(const QueueEffect &effect);
- static EffectQueue Queue(const QueueDelay &delay);
- template <typename T, typename U, typename... Args>
- static EffectQueue Queue(const T &first, const U &second, Args... rest);
- static EffectLevel Level(float intensity, float levelLow, float levelHigh);
- static EffectScale Scale(float intensity, float levelLow, float levelHigh);
- // Constants With Arbitrary Values
- static constexpr uint32_t CAL_VERSION = 2;
- static constexpr std::array<EffectLevel, 2> V_TICK_DEFAULT = {1, 100};
- static constexpr std::array<EffectLevel, 2> V_CLICK_DEFAULT{1, 100};
- static constexpr std::array<EffectLevel, 2> V_LONG_DEFAULT{1, 100};
- static constexpr std::array<EffectDuration, 14> EFFECT_DURATIONS{
- 0, 100, 30, 1000, 300, 130, 150, 500, 100, 15, 20, 1000, 1000, 1000};
- // Constants With Prescribed Values
- static const std::map<Effect, EffectIndex> EFFECT_INDEX{
- {Effect::CLICK, 2},
- {Effect::TICK, 2},
- {Effect::HEAVY_CLICK, 2},
- {Effect::TEXTURE_TICK, 9},
- };
- static constexpr uint32_t MIN_ON_OFF_INTERVAL_US = 8500;
- static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
- static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby
- static constexpr auto POLLING_TIMEOUT = 20;
- enum WaveformIndex : uint16_t {
- /* Physical waveform */
- WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
- WAVEFORM_RESERVED_INDEX_1 = 1,
- WAVEFORM_CLICK_INDEX = 2,
- WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
- WAVEFORM_THUD_INDEX = 4,
- WAVEFORM_SPIN_INDEX = 5,
- WAVEFORM_QUICK_RISE_INDEX = 6,
- WAVEFORM_SLOW_RISE_INDEX = 7,
- WAVEFORM_QUICK_FALL_INDEX = 8,
- WAVEFORM_LIGHT_TICK_INDEX = 9,
- WAVEFORM_LOW_TICK_INDEX = 10,
- WAVEFORM_RESERVED_MFG_1,
- WAVEFORM_RESERVED_MFG_2,
- WAVEFORM_RESERVED_MFG_3,
- WAVEFORM_MAX_PHYSICAL_INDEX,
- /* OWT waveform */
- WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
- WAVEFORM_PWLE,
- /*
- * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
- * #define FF_GAIN 0x60 // 96 in decimal
- * #define FF_MAX_EFFECTS FF_GAIN
- */
- WAVEFORM_MAX_INDEX,
- };
- static const EffectScale ON_GLOBAL_SCALE{levelToScale(V_LONG_DEFAULT[1])};
- static const EffectIndex ON_EFFECT_INDEX{0};
- static const std::map<EffectTuple, EffectScale> EFFECT_SCALE{
- {{Effect::TICK, EffectStrength::LIGHT},
- Scale(0.5f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::TICK, EffectStrength::MEDIUM},
- Scale(0.5f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::TICK, EffectStrength::STRONG},
- Scale(0.5f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::CLICK, EffectStrength::LIGHT},
- Scale(0.7f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::CLICK, EffectStrength::MEDIUM},
- Scale(0.7f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::CLICK, EffectStrength::STRONG},
- Scale(0.7f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::HEAVY_CLICK, EffectStrength::LIGHT},
- Scale(1.0f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::HEAVY_CLICK, EffectStrength::MEDIUM},
- Scale(1.0f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::HEAVY_CLICK, EffectStrength::STRONG},
- Scale(1.0f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- {{Effect::TEXTURE_TICK, EffectStrength::LIGHT},
- Scale(0.5f * 0.5f, V_TICK_DEFAULT[0], V_TICK_DEFAULT[1])},
- {{Effect::TEXTURE_TICK, EffectStrength::MEDIUM},
- Scale(0.5f * 0.7f, V_TICK_DEFAULT[0], V_TICK_DEFAULT[1])},
- {{Effect::TEXTURE_TICK, EffectStrength::STRONG},
- Scale(0.5f * 1.0f, V_TICK_DEFAULT[0], V_TICK_DEFAULT[1])},
- };
- static const std::map<EffectTuple, EffectQueue> EFFECT_QUEUE{
- {{Effect::DOUBLE_CLICK, EffectStrength::LIGHT},
- Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
- Level(0.7f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- 100,
- QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
- Level(1.0f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])})},
- {{Effect::DOUBLE_CLICK, EffectStrength::MEDIUM},
- Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
- Level(0.7f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- 100,
- QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
- Level(1.0f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])})},
- {{Effect::DOUBLE_CLICK, EffectStrength::STRONG},
- Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
- Level(0.7f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
- 100,
- QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
- Level(1.0f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])})},
- };
- EffectQueue Queue(const QueueEffect &effect) {
- auto index = std::get<0>(effect);
- auto level = std::get<1>(effect);
- auto string = std::to_string(index) + "." + std::to_string(level);
- auto duration = EFFECT_DURATIONS[index];
- return {string, duration};
- }
- EffectQueue Queue(const QueueDelay &delay) {
- auto string = std::to_string(delay);
- return {string, delay};
- }
- template <typename T, typename U, typename... Args>
- EffectQueue Queue(const T &first, const U &second, Args... rest) {
- auto head = Queue(first);
- auto tail = Queue(second, rest...);
- auto string = std::get<0>(head) + "," + std::get<0>(tail);
- auto duration = std::get<1>(head) + std::get<1>(tail);
- return {string, duration};
- }
- static EffectLevel Level(float intensity, float levelLow, float levelHigh) {
- return std::lround(intensity * (levelHigh - levelLow)) + levelLow;
- }
- static EffectScale Scale(float intensity, float levelLow, float levelHigh) {
- return levelToScale(Level(intensity, levelLow, levelHigh));
- }
- class VibratorTest : public Test {
- public:
- void SetUp() override {
- setenv("INPUT_EVENT_NAME", "CS40L26TestSuite", true);
- std::unique_ptr<MockApi> mockapi;
- std::unique_ptr<MockCal> mockcal;
- createMock(&mockapi, &mockcal);
- createVibrator(std::move(mockapi), std::move(mockcal));
- }
- void TearDown() override { deleteVibrator(); }
- protected:
- void createMock(std::unique_ptr<MockApi> *mockapi, std::unique_ptr<MockCal> *mockcal) {
- *mockapi = std::make_unique<MockApi>();
- *mockcal = std::make_unique<MockCal>();
- mMockApi = mockapi->get();
- mMockCal = mockcal->get();
- ON_CALL(*mMockApi, destructor()).WillByDefault(Assign(&mMockApi, nullptr));
- ON_CALL(*mMockApi, setFFGain(_, _)).WillByDefault(Return(true));
- ON_CALL(*mMockApi, setFFEffect(_, _, _)).WillByDefault(Return(true));
- ON_CALL(*mMockApi, setFFPlay(_, _, _)).WillByDefault(Return(true));
- ON_CALL(*mMockApi, pollVibeState(_, _)).WillByDefault(Return(true));
- ON_CALL(*mMockApi, uploadOwtEffect(_, _, _, _, _, _)).WillByDefault(Return(true));
- ON_CALL(*mMockApi, eraseOwtEffect(_, _, _)).WillByDefault(Return(true));
- ON_CALL(*mMockApi, getOwtFreeSpace(_))
- .WillByDefault(DoAll(SetArgPointee<0>(11504), Return(true)));
- ON_CALL(*mMockCal, destructor()).WillByDefault(Assign(&mMockCal, nullptr));
- ON_CALL(*mMockCal, getVersion(_))
- .WillByDefault(DoAll(SetArgPointee<0>(CAL_VERSION), Return(true)));
- ON_CALL(*mMockCal, getTickVolLevels(_))
- .WillByDefault(DoAll(SetArgPointee<0>(V_TICK_DEFAULT), Return(true)));
- ON_CALL(*mMockCal, getClickVolLevels(_))
- .WillByDefault(DoAll(SetArgPointee<0>(V_CLICK_DEFAULT), Return(true)));
- ON_CALL(*mMockCal, getLongVolLevels(_))
- .WillByDefault(DoAll(SetArgPointee<0>(V_LONG_DEFAULT), Return(true)));
- relaxMock(false);
- }
- void createVibrator(std::unique_ptr<MockApi> mockapi, std::unique_ptr<MockCal> mockcal,
- bool relaxed = true) {
- if (relaxed) {
- relaxMock(true);
- }
- mVibrator = ndk::SharedRefBase::make<Vibrator>(std::move(mockapi), std::move(mockcal));
- if (relaxed) {
- relaxMock(false);
- }
- }
- void deleteVibrator(bool relaxed = true) {
- if (relaxed) {
- relaxMock(true);
- }
- mVibrator.reset();
- }
- private:
- void relaxMock(bool relax) {
- auto times = relax ? AnyNumber() : Exactly(0);
- Mock::VerifyAndClearExpectations(mMockApi);
- Mock::VerifyAndClearExpectations(mMockCal);
- EXPECT_CALL(*mMockApi, destructor()).Times(times);
- EXPECT_CALL(*mMockApi, setF0(_)).Times(times);
- EXPECT_CALL(*mMockApi, setF0Offset(_)).Times(times);
- EXPECT_CALL(*mMockApi, setRedc(_)).Times(times);
- EXPECT_CALL(*mMockApi, setQ(_)).Times(times);
- EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).Times(times);
- EXPECT_CALL(*mMockApi, getOwtFreeSpace(_)).Times(times);
- EXPECT_CALL(*mMockApi, setF0CompEnable(_)).Times(times);
- EXPECT_CALL(*mMockApi, setRedcCompEnable(_)).Times(times);
- EXPECT_CALL(*mMockApi, pollVibeState(_, _)).Times(times);
- EXPECT_CALL(*mMockApi, setFFGain(_, _)).Times(times);
- EXPECT_CALL(*mMockApi, setFFEffect(_, _, _)).Times(times);
- EXPECT_CALL(*mMockApi, setFFPlay(_, _, _)).Times(times);
- EXPECT_CALL(*mMockApi, setMinOnOffInterval(_)).Times(times);
- EXPECT_CALL(*mMockApi, getContextScale()).Times(times);
- EXPECT_CALL(*mMockApi, getContextEnable()).Times(times);
- EXPECT_CALL(*mMockApi, getContextSettlingTime()).Times(times);
- EXPECT_CALL(*mMockApi, getContextCooldownTime()).Times(times);
- EXPECT_CALL(*mMockApi, getContextFadeEnable()).Times(times);
- EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).Times(times);
- EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, _, _, _)).Times(times);
- EXPECT_CALL(*mMockApi, debug(_)).Times(times);
- EXPECT_CALL(*mMockCal, destructor()).Times(times);
- EXPECT_CALL(*mMockCal, getF0(_)).Times(times);
- EXPECT_CALL(*mMockCal, getRedc(_)).Times(times);
- EXPECT_CALL(*mMockCal, getQ(_)).Times(times);
- EXPECT_CALL(*mMockCal, getTickVolLevels(_)).Times(times);
- EXPECT_CALL(*mMockCal, getClickVolLevels(_)).Times(times);
- EXPECT_CALL(*mMockCal, getLongVolLevels(_)).Times(times);
- EXPECT_CALL(*mMockCal, isChirpEnabled()).Times(times);
- EXPECT_CALL(*mMockCal, getLongFrequencyShift(_)).Times(times);
- EXPECT_CALL(*mMockCal, isF0CompEnabled()).Times(times);
- EXPECT_CALL(*mMockCal, isRedcCompEnabled()).Times(times);
- EXPECT_CALL(*mMockCal, debug(_)).Times(times);
- }
- protected:
- MockApi *mMockApi;
- MockCal *mMockCal;
- std::shared_ptr<IVibrator> mVibrator;
- uint32_t mEffectIndex;
- };
- TEST_F(VibratorTest, Constructor) {
- std::unique_ptr<MockApi> mockapi;
- std::unique_ptr<MockCal> mockcal;
- std::string f0Val = std::to_string(std::rand());
- std::string redcVal = std::to_string(std::rand());
- std::string qVal = std::to_string(std::rand());
- uint32_t calVer;
- uint32_t supportedPrimitivesBits = 0x0;
- Expectation volGet;
- Sequence f0Seq, redcSeq, qSeq, supportedPrimitivesSeq;
- EXPECT_CALL(*mMockApi, destructor()).WillOnce(DoDefault());
- EXPECT_CALL(*mMockCal, destructor()).WillOnce(DoDefault());
- deleteVibrator(false);
- createMock(&mockapi, &mockcal);
- EXPECT_CALL(*mMockCal, getF0(_))
- .InSequence(f0Seq)
- .WillOnce(DoAll(SetArgReferee<0>(f0Val), Return(true)));
- EXPECT_CALL(*mMockApi, setF0(f0Val)).InSequence(f0Seq).WillOnce(Return(true));
- EXPECT_CALL(*mMockCal, getRedc(_))
- .InSequence(redcSeq)
- .WillOnce(DoAll(SetArgReferee<0>(redcVal), Return(true)));
- EXPECT_CALL(*mMockApi, setRedc(redcVal)).InSequence(redcSeq).WillOnce(Return(true));
- EXPECT_CALL(*mMockCal, getQ(_))
- .InSequence(qSeq)
- .WillOnce(DoAll(SetArgReferee<0>(qVal), Return(true)));
- EXPECT_CALL(*mMockApi, setQ(qVal)).InSequence(qSeq).WillOnce(Return(true));
- EXPECT_CALL(*mMockCal, getLongFrequencyShift(_)).WillOnce(Return(true));
- mMockCal->getVersion(&calVer);
- if (calVer == 2) {
- volGet = EXPECT_CALL(*mMockCal, getTickVolLevels(_)).WillOnce(DoDefault());
- volGet = EXPECT_CALL(*mMockCal, getClickVolLevels(_)).WillOnce(DoDefault());
- volGet = EXPECT_CALL(*mMockCal, getLongVolLevels(_)).WillOnce(DoDefault());
- }
- EXPECT_CALL(*mMockCal, isF0CompEnabled()).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, setF0CompEnable(true)).WillOnce(Return(true));
- EXPECT_CALL(*mMockCal, isRedcCompEnabled()).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, setRedcCompEnable(true)).WillOnce(Return(true));
- EXPECT_CALL(*mMockCal, isChirpEnabled()).WillOnce(Return(true));
- EXPECT_CALL(*mMockCal, getSupportedPrimitives(_))
- .InSequence(supportedPrimitivesSeq)
- .WillOnce(DoAll(SetArgPointee<0>(supportedPrimitivesBits), Return(true)));
- EXPECT_CALL(*mMockApi, setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US)).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, getContextScale()).WillOnce(Return(0));
- EXPECT_CALL(*mMockApi, getContextEnable()).WillOnce(Return(false));
- EXPECT_CALL(*mMockApi, getContextSettlingTime()).WillOnce(Return(0));
- EXPECT_CALL(*mMockApi, getContextCooldownTime()).WillOnce(Return(0));
- EXPECT_CALL(*mMockApi, getContextFadeEnable()).WillOnce(Return(false));
- createVibrator(std::move(mockapi), std::move(mockcal), false);
- }
- TEST_F(VibratorTest, on) {
- Sequence s1, s2;
- uint16_t duration = std::rand() + 1;
- EXPECT_CALL(*mMockApi, setFFGain(_, ON_GLOBAL_SCALE)).InSequence(s1).WillOnce(DoDefault());
- EXPECT_CALL(*mMockApi, setFFEffect(_, _, duration + MAX_COLD_START_LATENCY_MS))
- .InSequence(s2)
- .WillOnce(DoDefault());
- EXPECT_CALL(*mMockApi, setFFPlay(_, ON_EFFECT_INDEX, true))
- .InSequence(s1, s2)
- .WillOnce(DoDefault());
- EXPECT_TRUE(mVibrator->on(duration, nullptr).isOk());
- }
- TEST_F(VibratorTest, off) {
- Sequence s1;
- EXPECT_CALL(*mMockApi, setFFGain(_, ON_GLOBAL_SCALE)).InSequence(s1).WillOnce(DoDefault());
- EXPECT_TRUE(mVibrator->off().isOk());
- }
- TEST_F(VibratorTest, supportsAmplitudeControl_supported) {
- int32_t capabilities;
- EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(true));
- EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
- EXPECT_GT(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
- }
- TEST_F(VibratorTest, supportsExternalAmplitudeControl_unsupported) {
- int32_t capabilities;
- EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(true));
- EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
- EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL, 0);
- }
- TEST_F(VibratorTest, setAmplitude_supported) {
- EffectAmplitude amplitude = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
- EXPECT_CALL(*mMockApi, setFFGain(_, amplitudeToScale(amplitude))).WillOnce(Return(true));
- EXPECT_TRUE(mVibrator->setAmplitude(amplitude).isOk());
- }
- TEST_F(VibratorTest, supportsExternalControl_supported) {
- int32_t capabilities;
- EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(true));
- EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
- EXPECT_GT(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
- }
- TEST_F(VibratorTest, supportsExternalControl_unsupported) {
- int32_t capabilities;
- EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(false));
- EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
- EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
- }
- TEST_F(VibratorTest, setExternalControl_enable) {
- Sequence s1, s2;
- EXPECT_CALL(*mMockApi, setFFGain(_, ON_GLOBAL_SCALE)).InSequence(s1).WillOnce(DoDefault());
- EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).InSequence(s2).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, true, _, _))
- .InSequence(s1, s2)
- .WillOnce(Return(true));
- EXPECT_TRUE(mVibrator->setExternalControl(true).isOk());
- }
- TEST_F(VibratorTest, setExternalControl_disable) {
- Sequence s1, s2, s3, s4;
- // The default mIsUnderExternalControl is false, so it needs to turn on the External Control
- // to make mIsUnderExternalControl become true.
- EXPECT_CALL(*mMockApi, setFFGain(_, ON_GLOBAL_SCALE))
- .InSequence(s1)
- .InSequence(s1)
- .WillOnce(DoDefault());
- EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).InSequence(s2).WillOnce(Return(true));
- EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, true, _, _)).InSequence(s3).WillOnce(Return(true));
- EXPECT_TRUE(mVibrator->setExternalControl(true).isOk());
- EXPECT_CALL(*mMockApi, setFFGain(_, levelToScale(VOLTAGE_SCALE_MAX)))
- .InSequence(s4)
- .WillOnce(DoDefault());
- EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, false, _, _))
- .InSequence(s1, s2, s3, s4)
- .WillOnce(Return(true));
- EXPECT_TRUE(mVibrator->setExternalControl(false).isOk());
- }
- class EffectsTest : public VibratorTest, public WithParamInterface<EffectTuple> {
- public:
- static auto PrintParam(const TestParamInfo<ParamType> &info) {
- auto param = info.param;
- auto effect = std::get<0>(param);
- auto strength = std::get<1>(param);
- return toString(effect) + "_" + toString(strength);
- }
- };
- TEST_P(EffectsTest, perform) {
- auto param = GetParam();
- auto effect = std::get<0>(param);
- auto strength = std::get<1>(param);
- auto scale = EFFECT_SCALE.find(param);
- auto queue = EFFECT_QUEUE.find(param);
- EffectDuration duration;
- auto callback = ndk::SharedRefBase::make<MockVibratorCallback>();
- std::promise<void> promise;
- std::future<void> future{promise.get_future()};
- auto complete = [&promise] {
- promise.set_value();
- return ndk::ScopedAStatus::ok();
- };
- bool composeEffect;
- ExpectationSet eSetup;
- Expectation eActivate, ePollHaptics, ePollStop, eEraseDone;
- if (scale != EFFECT_SCALE.end()) {
- EffectIndex index = EFFECT_INDEX.at(effect);
- duration = EFFECT_DURATIONS[index];
- eSetup += EXPECT_CALL(*mMockApi, setFFGain(_, levelToScale(scale->second)))
- .WillOnce(DoDefault());
- eActivate = EXPECT_CALL(*mMockApi, setFFPlay(_, index, true))
- .After(eSetup)
- .WillOnce(DoDefault());
- } else if (queue != EFFECT_QUEUE.end()) {
- duration = std::get<1>(queue->second);
- eSetup += EXPECT_CALL(*mMockApi, setFFGain(_, ON_GLOBAL_SCALE))
- .After(eSetup)
- .WillOnce(DoDefault());
- eSetup += EXPECT_CALL(*mMockApi, getOwtFreeSpace(_)).WillOnce(DoDefault());
- eSetup += EXPECT_CALL(*mMockApi, uploadOwtEffect(_, _, _, _, _, _))
- .After(eSetup)
- .WillOnce(DoDefault());
- eActivate = EXPECT_CALL(*mMockApi, setFFPlay(_, WAVEFORM_COMPOSE, true))
- .After(eSetup)
- .WillOnce(DoDefault());
- composeEffect = true;
- } else {
- duration = 0;
- }
- if (duration) {
- ePollHaptics = EXPECT_CALL(*mMockApi, pollVibeState(1, POLLING_TIMEOUT))
- .After(eActivate)
- .WillOnce(DoDefault());
- ePollStop = EXPECT_CALL(*mMockApi, pollVibeState(0, -1))
- .After(ePollHaptics)
- .WillOnce(DoDefault());
- if (composeEffect) {
- eEraseDone = EXPECT_CALL(*mMockApi, eraseOwtEffect(_, _, _))
- .After(ePollStop)
- .WillOnce(DoDefault());
- EXPECT_CALL(*callback, onComplete()).After(eEraseDone).WillOnce(complete);
- } else {
- EXPECT_CALL(*callback, onComplete()).After(ePollStop).WillOnce(complete);
- }
- }
- int32_t lengthMs;
- ndk::ScopedAStatus status = mVibrator->perform(effect, strength, callback, &lengthMs);
- if (status.isOk()) {
- EXPECT_LE(duration, lengthMs);
- } else {
- EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
- EXPECT_EQ(0, lengthMs);
- }
- if (duration) {
- EXPECT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready);
- }
- }
- const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
- ndk::enum_range<Effect>().end()};
- const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
- ndk::enum_range<EffectStrength>().end()};
- INSTANTIATE_TEST_CASE_P(VibratorTests, EffectsTest,
- Combine(ValuesIn(kEffects.begin(), kEffects.end()),
- ValuesIn(kEffectStrengths.begin(), kEffectStrengths.end())),
- EffectsTest::PrintParam);
- struct PrimitiveParam {
- CompositePrimitive primitive;
- EffectIndex index;
- };
- class PrimitiveTest : public VibratorTest, public WithParamInterface<PrimitiveParam> {
- public:
- static auto PrintParam(const TestParamInfo<ParamType> &info) {
- return toString(info.param.primitive);
- }
- };
- const std::vector<PrimitiveParam> kPrimitiveParams = {
- {CompositePrimitive::CLICK, 2}, {CompositePrimitive::THUD, 4},
- {CompositePrimitive::SPIN, 5}, {CompositePrimitive::QUICK_RISE, 6},
- {CompositePrimitive::SLOW_RISE, 7}, {CompositePrimitive::QUICK_FALL, 8},
- {CompositePrimitive::LIGHT_TICK, 9}, {CompositePrimitive::LOW_TICK, 10},
- };
- TEST_P(PrimitiveTest, getPrimitiveDuration) {
- auto param = GetParam();
- auto primitive = param.primitive;
- auto index = param.index;
- int32_t duration;
- EXPECT_EQ(EX_NONE, mVibrator->getPrimitiveDuration(primitive, &duration).getExceptionCode());
- EXPECT_EQ(EFFECT_DURATIONS[index], duration);
- }
- INSTANTIATE_TEST_CASE_P(VibratorTests, PrimitiveTest,
- ValuesIn(kPrimitiveParams.begin(), kPrimitiveParams.end()),
- PrimitiveTest::PrintParam);
- struct ComposeParam {
- std::string name;
- std::vector<CompositeEffect> composite;
- EffectQueue queue;
- };
- class ComposeTest : public VibratorTest, public WithParamInterface<ComposeParam> {
- public:
- static auto PrintParam(const TestParamInfo<ParamType> &info) { return info.param.name; }
- };
- TEST_P(ComposeTest, compose) {
- auto param = GetParam();
- auto composite = param.composite;
- auto queue = std::get<0>(param.queue);
- ExpectationSet eSetup;
- Expectation eActivate, ePollHaptics, ePollStop, eEraseDone;
- auto callback = ndk::SharedRefBase::make<MockVibratorCallback>();
- std::promise<void> promise;
- std::future<void> future{promise.get_future()};
- auto complete = [&promise] {
- promise.set_value();
- return ndk::ScopedAStatus::ok();
- };
- eSetup += EXPECT_CALL(*mMockApi, setFFGain(_, ON_GLOBAL_SCALE))
- .After(eSetup)
- .WillOnce(DoDefault());
- eSetup += EXPECT_CALL(*mMockApi, getOwtFreeSpace(_)).WillOnce(DoDefault());
- eSetup += EXPECT_CALL(*mMockApi, uploadOwtEffect(_, _, _, _, _, _))
- .After(eSetup)
- .WillOnce(DoDefault());
- eActivate = EXPECT_CALL(*mMockApi, setFFPlay(_, WAVEFORM_COMPOSE, true))
- .After(eSetup)
- .WillOnce(DoDefault());
- ePollHaptics = EXPECT_CALL(*mMockApi, pollVibeState(1, POLLING_TIMEOUT))
- .After(eActivate)
- .WillOnce(DoDefault());
- ePollStop =
- EXPECT_CALL(*mMockApi, pollVibeState(0, -1)).After(ePollHaptics).WillOnce(DoDefault());
- eEraseDone =
- EXPECT_CALL(*mMockApi, eraseOwtEffect(_, _, _)).After(ePollStop).WillOnce(DoDefault());
- EXPECT_CALL(*callback, onComplete()).After(eEraseDone).WillOnce(complete);
- EXPECT_EQ(EX_NONE, mVibrator->compose(composite, callback).getExceptionCode());
- EXPECT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready);
- }
- const std::vector<ComposeParam> kComposeParams = {
- {"click",
- {{0, CompositePrimitive::CLICK, 1.0f}},
- Queue(QueueEffect(2, Level(1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
- {"thud",
- {{1, CompositePrimitive::THUD, 0.8f}},
- Queue(1, QueueEffect(4, Level(0.8f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
- {"spin",
- {{2, CompositePrimitive::SPIN, 0.6f}},
- Queue(2, QueueEffect(5, Level(0.6f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
- {"quick_rise",
- {{3, CompositePrimitive::QUICK_RISE, 0.4f}},
- Queue(3, QueueEffect(6, Level(0.4f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])), 0)},
- {"slow_rise",
- {{4, CompositePrimitive::SLOW_RISE, 0.0f}},
- Queue(4, QueueEffect(7, Level(0.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
- {"quick_fall",
- {{5, CompositePrimitive::QUICK_FALL, 1.0f}},
- Queue(5, QueueEffect(8, Level(1.0f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])), 0)},
- {"pop",
- {{6, CompositePrimitive::SLOW_RISE, 1.0f}, {50, CompositePrimitive::THUD, 1.0f}},
- Queue(6, QueueEffect(7, Level(1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 50,
- QueueEffect(4, Level(1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
- {"snap",
- {{7, CompositePrimitive::QUICK_RISE, 1.0f}, {0, CompositePrimitive::QUICK_FALL, 1.0f}},
- Queue(7, QueueEffect(6, Level(1.0f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])),
- QueueEffect(8, Level(1.0f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])), 0)},
- };
- INSTANTIATE_TEST_CASE_P(VibratorTests, ComposeTest,
- ValuesIn(kComposeParams.begin(), kComposeParams.end()),
- ComposeTest::PrintParam);
- } // namespace vibrator
- } // namespace hardware
- } // namespace android
- } // namespace aidl
|