1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
18 #include <android-base/logging.h>
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <future>
23 
24 #include "Vibrator.h"
25 #include "mocks.h"
26 #include "types.h"
27 #include "utils.h"
28 
29 namespace aidl {
30 namespace android {
31 namespace hardware {
32 namespace vibrator {
33 
34 using ::testing::_;
35 using ::testing::AnyNumber;
36 using ::testing::Assign;
37 using ::testing::AtLeast;
38 using ::testing::AtMost;
39 using ::testing::Combine;
40 using ::testing::DoAll;
41 using ::testing::DoDefault;
42 using ::testing::Exactly;
43 using ::testing::Expectation;
44 using ::testing::ExpectationSet;
45 using ::testing::Ge;
46 using ::testing::Mock;
47 using ::testing::MockFunction;
48 using ::testing::Range;
49 using ::testing::Return;
50 using ::testing::Sequence;
51 using ::testing::SetArgPointee;
52 using ::testing::Test;
53 using ::testing::TestParamInfo;
54 using ::testing::ValuesIn;
55 using ::testing::WithParamInterface;
56 
57 // Forward Declarations
58 
59 static EffectQueue Queue(const QueueEffect &effect);
60 static EffectQueue Queue(const QueueDelay &delay);
61 template <typename T, typename U, typename... Args>
62 static EffectQueue Queue(const T &first, const U &second, Args... rest);
63 
64 static EffectLevel Level(float intensity);
65 static EffectScale Scale(float intensity);
66 
67 // Constants With Arbitrary Values
68 
69 static constexpr uint32_t CAL_VERSION = 1;
70 static constexpr std::array<EffectLevel, 6> V_LEVELS{40, 50, 60, 70, 80, 90};
71 static constexpr std::array<EffectDuration, 10> EFFECT_DURATIONS{0,   0,   15,  0,   50,
72                                                                  100, 150, 200, 250, 8};
73 
74 // Constants With Prescribed Values
75 
76 static const std::map<Effect, EffectIndex> EFFECT_INDEX{
77         {Effect::CLICK, 2},
78         {Effect::TICK, 2},
79         {Effect::HEAVY_CLICK, 2},
80         {Effect::TEXTURE_TICK, 9},
81 };
82 
83 static constexpr EffectIndex QUEUE_INDEX{65534};
84 
85 static const EffectScale ON_GLOBAL_SCALE{levelToScale(V_LEVELS[5])};
86 static const EffectIndex ON_EFFECT_INDEX{0};
87 
88 static const std::map<EffectTuple, EffectScale> EFFECT_SCALE{
89         {{Effect::CLICK, EffectStrength::LIGHT}, Scale(0.7f * 0.5f)},
90         {{Effect::CLICK, EffectStrength::MEDIUM}, Scale(0.7f * 0.7f)},
91         {{Effect::CLICK, EffectStrength::STRONG}, Scale(0.7f * 1.0f)},
92         {{Effect::TICK, EffectStrength::LIGHT}, Scale(0.5f * 0.5f)},
93         {{Effect::TICK, EffectStrength::MEDIUM}, Scale(0.5f * 0.7f)},
94         {{Effect::TICK, EffectStrength::STRONG}, Scale(0.5f * 1.0f)},
95         {{Effect::HEAVY_CLICK, EffectStrength::LIGHT}, Scale(1.0f * 0.5f)},
96         {{Effect::HEAVY_CLICK, EffectStrength::MEDIUM}, Scale(1.0f * 0.7f)},
97         {{Effect::HEAVY_CLICK, EffectStrength::STRONG}, Scale(1.0f * 1.0f)},
98         {{Effect::TEXTURE_TICK, EffectStrength::LIGHT}, Scale(0.5f * 0.5f)},
99         {{Effect::TEXTURE_TICK, EffectStrength::MEDIUM}, Scale(0.5f * 0.7f)},
100         {{Effect::TEXTURE_TICK, EffectStrength::STRONG}, Scale(0.5f * 1.0f)},
101 };
102 
103 static const std::map<EffectTuple, EffectQueue> EFFECT_QUEUE{
104         {{Effect::DOUBLE_CLICK, EffectStrength::LIGHT},
105          Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK), Level(0.7f * 0.5f)}, 100,
106                QueueEffect{EFFECT_INDEX.at(Effect::CLICK), Level(1.0f * 0.5f)})},
107         {{Effect::DOUBLE_CLICK, EffectStrength::MEDIUM},
108          Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK), Level(0.7f * 0.7f)}, 100,
109                QueueEffect{EFFECT_INDEX.at(Effect::CLICK), Level(1.0f * 0.7f)})},
110         {{Effect::DOUBLE_CLICK, EffectStrength::STRONG},
111          Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK), Level(0.7f * 1.0f)}, 100,
112                QueueEffect{EFFECT_INDEX.at(Effect::CLICK), Level(1.0f * 1.0f)})},
113 };
114 
Queue(const QueueEffect & effect)115 EffectQueue Queue(const QueueEffect &effect) {
116     auto index = std::get<0>(effect);
117     auto level = std::get<1>(effect);
118     auto string = std::to_string(index) + "." + std::to_string(level);
119     auto duration = EFFECT_DURATIONS[index];
120     return {string, duration};
121 }
122 
Queue(const QueueDelay & delay)123 EffectQueue Queue(const QueueDelay &delay) {
124     auto string = std::to_string(delay);
125     return {string, delay};
126 }
127 
128 template <typename T, typename U, typename... Args>
Queue(const T & first,const U & second,Args...rest)129 EffectQueue Queue(const T &first, const U &second, Args... rest) {
130     auto head = Queue(first);
131     auto tail = Queue(second, rest...);
132     auto string = std::get<0>(head) + "," + std::get<0>(tail);
133     auto duration = std::get<1>(head) + std::get<1>(tail);
134     return {string, duration};
135 }
136 
Level(float intensity)137 static EffectLevel Level(float intensity) {
138     auto vMin = std::max(V_LEVELS[0] - (V_LEVELS[4] - V_LEVELS[0]) / 4.0f, 4.0f);
139     auto vMax = V_LEVELS[4];
140     return std::lround(intensity * (vMax - vMin)) + vMin;
141 }
142 
Scale(float intensity)143 static EffectScale Scale(float intensity) {
144     return levelToScale(Level(intensity));
145 }
146 
147 class VibratorTest : public Test {
148   public:
SetUp()149     void SetUp() override {
150         std::unique_ptr<MockApi> mockapi;
151         std::unique_ptr<MockCal> mockcal;
152 
153         createMock(&mockapi, &mockcal);
154         createVibrator(std::move(mockapi), std::move(mockcal));
155     }
156 
TearDown()157     void TearDown() override { deleteVibrator(); }
158 
159   protected:
createMock(std::unique_ptr<MockApi> * mockapi,std::unique_ptr<MockCal> * mockcal)160     void createMock(std::unique_ptr<MockApi> *mockapi, std::unique_ptr<MockCal> *mockcal) {
161         *mockapi = std::make_unique<MockApi>();
162         *mockcal = std::make_unique<MockCal>();
163 
164         mMockApi = mockapi->get();
165         mMockCal = mockcal->get();
166 
167         ON_CALL(*mMockApi, destructor()).WillByDefault(Assign(&mMockApi, nullptr));
168 
169         ON_CALL(*mMockApi, getEffectCount(_))
170                 .WillByDefault(DoAll(SetArgPointee<0>(EFFECT_DURATIONS.size()), Return(true)));
171 
172         ON_CALL(*mMockApi, setEffectIndex(_))
173                 .WillByDefault(Invoke(this, &VibratorTest::setEffectIndex));
174 
175         ON_CALL(*mMockApi, getEffectDuration(_))
176                 .WillByDefault(Invoke(this, &VibratorTest::getEffectDuration));
177 
178         ON_CALL(*mMockCal, destructor()).WillByDefault(Assign(&mMockCal, nullptr));
179 
180         ON_CALL(*mMockCal, getVersion(_))
181                 .WillByDefault(DoAll(SetArgPointee<0>(CAL_VERSION), Return(true)));
182 
183         ON_CALL(*mMockCal, getVolLevels(_))
184                 .WillByDefault(DoAll(SetArgPointee<0>(V_LEVELS), Return(true)));
185 
186         relaxMock(false);
187     }
188 
createVibrator(std::unique_ptr<MockApi> mockapi,std::unique_ptr<MockCal> mockcal,bool relaxed=true)189     void createVibrator(std::unique_ptr<MockApi> mockapi, std::unique_ptr<MockCal> mockcal,
190                         bool relaxed = true) {
191         if (relaxed) {
192             relaxMock(true);
193         }
194         mVibrator = ndk::SharedRefBase::make<Vibrator>(std::move(mockapi), std::move(mockcal));
195         if (relaxed) {
196             relaxMock(false);
197         }
198     }
199 
deleteVibrator(bool relaxed=true)200     void deleteVibrator(bool relaxed = true) {
201         if (relaxed) {
202             relaxMock(true);
203         }
204         mVibrator.reset();
205     }
206 
setEffectIndex(EffectIndex index)207     bool setEffectIndex(EffectIndex index) {
208         mEffectIndex = index;
209         return true;
210     }
211 
getEffectDuration(EffectDuration * duration)212     bool getEffectDuration(EffectDuration *duration) {
213         if (mEffectIndex < EFFECT_DURATIONS.size()) {
214             *duration = msToCycles(EFFECT_DURATIONS[mEffectIndex]);
215             return true;
216         } else {
217             return false;
218         }
219     }
220 
221   private:
relaxMock(bool relax)222     void relaxMock(bool relax) {
223         auto times = relax ? AnyNumber() : Exactly(0);
224 
225         Mock::VerifyAndClearExpectations(mMockApi);
226         Mock::VerifyAndClearExpectations(mMockCal);
227 
228         EXPECT_CALL(*mMockApi, destructor()).Times(times);
229         EXPECT_CALL(*mMockApi, setF0(_)).Times(times);
230         EXPECT_CALL(*mMockApi, setRedc(_)).Times(times);
231         EXPECT_CALL(*mMockApi, setQ(_)).Times(times);
232         EXPECT_CALL(*mMockApi, setActivate(_)).Times(times);
233         EXPECT_CALL(*mMockApi, setDuration(_)).Times(times);
234         EXPECT_CALL(*mMockApi, getEffectCount(_)).Times(times);
235         EXPECT_CALL(*mMockApi, getEffectDuration(_)).Times(times);
236         EXPECT_CALL(*mMockApi, setEffectIndex(_)).Times(times);
237         EXPECT_CALL(*mMockApi, setEffectQueue(_)).Times(times);
238         EXPECT_CALL(*mMockApi, hasEffectScale()).Times(times);
239         EXPECT_CALL(*mMockApi, setEffectScale(_)).Times(times);
240         EXPECT_CALL(*mMockApi, setGlobalScale(_)).Times(times);
241         EXPECT_CALL(*mMockApi, setState(_)).Times(times);
242         EXPECT_CALL(*mMockApi, hasAspEnable()).Times(times);
243         EXPECT_CALL(*mMockApi, getAspEnable(_)).Times(times);
244         EXPECT_CALL(*mMockApi, setAspEnable(_)).Times(times);
245         EXPECT_CALL(*mMockApi, setGpioFallIndex(_)).Times(times);
246         EXPECT_CALL(*mMockApi, setGpioFallScale(_)).Times(times);
247         EXPECT_CALL(*mMockApi, setGpioRiseIndex(_)).Times(times);
248         EXPECT_CALL(*mMockApi, setGpioRiseScale(_)).Times(times);
249         EXPECT_CALL(*mMockApi, debug(_)).Times(times);
250 
251         EXPECT_CALL(*mMockCal, destructor()).Times(times);
252         EXPECT_CALL(*mMockCal, getF0(_)).Times(times);
253         EXPECT_CALL(*mMockCal, getRedc(_)).Times(times);
254         EXPECT_CALL(*mMockCal, getQ(_)).Times(times);
255         EXPECT_CALL(*mMockCal, getVolLevels(_)).Times(times);
256         EXPECT_CALL(*mMockCal, debug(_)).Times(times);
257     }
258 
259   protected:
260     MockApi *mMockApi;
261     MockCal *mMockCal;
262     std::shared_ptr<IVibrator> mVibrator;
263     uint32_t mEffectIndex;
264 };
265 
TEST_F(VibratorTest,Constructor)266 TEST_F(VibratorTest, Constructor) {
267     std::unique_ptr<MockApi> mockapi;
268     std::unique_ptr<MockCal> mockcal;
269     uint32_t f0Val = std::rand();
270     uint32_t redcVal = std::rand();
271     uint32_t qVal = std::rand();
272     uint32_t calVer;
273     Expectation volGet;
274     Sequence f0Seq, redcSeq, qSeq, volSeq, durSeq;
275 
276     EXPECT_CALL(*mMockApi, destructor()).WillOnce(DoDefault());
277     EXPECT_CALL(*mMockCal, destructor()).WillOnce(DoDefault());
278 
279     deleteVibrator(false);
280 
281     createMock(&mockapi, &mockcal);
282 
283     EXPECT_CALL(*mMockCal, getF0(_))
284             .InSequence(f0Seq)
285             .WillOnce(DoAll(SetArgPointee<0>(f0Val), Return(true)));
286     EXPECT_CALL(*mMockApi, setF0(f0Val)).InSequence(f0Seq).WillOnce(Return(true));
287 
288     EXPECT_CALL(*mMockCal, getRedc(_))
289             .InSequence(redcSeq)
290             .WillOnce(DoAll(SetArgPointee<0>(redcVal), Return(true)));
291     EXPECT_CALL(*mMockApi, setRedc(redcVal)).InSequence(redcSeq).WillOnce(Return(true));
292 
293     EXPECT_CALL(*mMockCal, getQ(_))
294             .InSequence(qSeq)
295             .WillOnce(DoAll(SetArgPointee<0>(qVal), Return(true)));
296     EXPECT_CALL(*mMockApi, setQ(qVal)).InSequence(qSeq).WillOnce(Return(true));
297     if (mMockCal->getVersion(&calVer) == 1) {
298         volGet = EXPECT_CALL(*mMockCal, getVolLevels(_)).WillOnce(DoDefault());
299     } else {
300         volGet = EXPECT_CALL(*mMockCal, getTickVolLevels(_)).WillOnce(DoDefault());
301         volGet = EXPECT_CALL(*mMockCal, getClickVolLevels(_)).WillOnce(DoDefault());
302         volGet = EXPECT_CALL(*mMockCal, getLongVolLevels(_)).WillOnce(DoDefault());
303     }
304 
305     EXPECT_CALL(*mMockApi, setState(true)).WillOnce(Return(true));
306     EXPECT_CALL(*mMockApi, getEffectCount(_)).InSequence(durSeq).WillOnce(DoDefault());
307 
308     for (auto &d : EFFECT_DURATIONS) {
309         EXPECT_CALL(*mMockApi, setEffectIndex(&d - &EFFECT_DURATIONS[0]))
310                 .InSequence(durSeq)
311                 .WillOnce(DoDefault());
312         EXPECT_CALL(*mMockApi, getEffectDuration(_)).InSequence(durSeq).WillOnce(DoDefault());
313     }
314 
315     createVibrator(std::move(mockapi), std::move(mockcal), false);
316 }
317 
TEST_F(VibratorTest,on)318 TEST_F(VibratorTest, on) {
319     Sequence s1, s2, s3;
320     uint16_t duration = std::rand() + 1;
321 
322     EXPECT_CALL(*mMockApi, setGlobalScale(ON_GLOBAL_SCALE)).InSequence(s1).WillOnce(Return(true));
323     EXPECT_CALL(*mMockApi, setEffectIndex(ON_EFFECT_INDEX)).InSequence(s2).WillOnce(DoDefault());
324     EXPECT_CALL(*mMockApi, setDuration(Ge(duration))).InSequence(s3).WillOnce(Return(true));
325     EXPECT_CALL(*mMockApi, setActivate(true)).InSequence(s1, s2, s3).WillOnce(Return(true));
326 
327     EXPECT_TRUE(mVibrator->on(duration, nullptr).isOk());
328 }
329 
TEST_F(VibratorTest,off)330 TEST_F(VibratorTest, off) {
331     EXPECT_CALL(*mMockApi, setActivate(false)).WillOnce(Return(true));
332     EXPECT_CALL(*mMockApi, setGlobalScale(0)).WillOnce(Return(true));
333 
334     EXPECT_TRUE(mVibrator->off().isOk());
335 }
336 
TEST_F(VibratorTest,supportsAmplitudeControl_supported)337 TEST_F(VibratorTest, supportsAmplitudeControl_supported) {
338     EXPECT_CALL(*mMockApi, hasEffectScale()).WillOnce(Return(true));
339     EXPECT_CALL(*mMockApi, hasAspEnable()).WillOnce(Return(true));
340 
341     int32_t capabilities;
342     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
343     EXPECT_GT(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
344 }
345 
TEST_F(VibratorTest,supportsAmplitudeControl_unsupported1)346 TEST_F(VibratorTest, supportsAmplitudeControl_unsupported1) {
347     EXPECT_CALL(*mMockApi, hasEffectScale()).WillOnce(Return(false));
348     EXPECT_CALL(*mMockApi, hasAspEnable()).WillOnce(Return(true));
349 
350     int32_t capabilities;
351     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
352     EXPECT_EQ(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
353 }
354 
TEST_F(VibratorTest,supportsAmplitudeControl_unsupported2)355 TEST_F(VibratorTest, supportsAmplitudeControl_unsupported2) {
356     EXPECT_CALL(*mMockApi, hasEffectScale()).WillOnce(Return(false));
357     EXPECT_CALL(*mMockApi, hasAspEnable()).WillOnce(Return(false));
358 
359     int32_t capabilities;
360     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
361     EXPECT_EQ(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
362 }
363 
TEST_F(VibratorTest,supportsExternalAmplitudeControl_unsupported)364 TEST_F(VibratorTest, supportsExternalAmplitudeControl_unsupported) {
365     EXPECT_CALL(*mMockApi, hasEffectScale()).WillOnce(Return(true));
366     EXPECT_CALL(*mMockApi, hasAspEnable()).WillOnce(Return(true));
367 
368     int32_t capabilities;
369     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
370     EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL, 0);
371 }
372 
TEST_F(VibratorTest,setAmplitude_supported)373 TEST_F(VibratorTest, setAmplitude_supported) {
374     Sequence s;
375     EffectAmplitude amplitude = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
376 
377     EXPECT_CALL(*mMockApi, getAspEnable(_))
378             .InSequence(s)
379             .WillOnce(DoAll(SetArgPointee<0>(false), Return(true)));
380     EXPECT_CALL(*mMockApi, setEffectScale(amplitudeToScale(amplitude)))
381             .InSequence(s)
382             .WillOnce(Return(true));
383 
384     EXPECT_TRUE(mVibrator->setAmplitude(amplitude).isOk());
385 }
386 
TEST_F(VibratorTest,setAmplitude_unsupported)387 TEST_F(VibratorTest, setAmplitude_unsupported) {
388     EXPECT_CALL(*mMockApi, getAspEnable(_)).WillOnce(DoAll(SetArgPointee<0>(true), Return(true)));
389 
390     EXPECT_EQ(EX_UNSUPPORTED_OPERATION, mVibrator->setAmplitude(1).getExceptionCode());
391 }
392 
TEST_F(VibratorTest,supportsExternalControl_supported)393 TEST_F(VibratorTest, supportsExternalControl_supported) {
394     EXPECT_CALL(*mMockApi, hasEffectScale()).WillOnce(Return(true));
395     EXPECT_CALL(*mMockApi, hasAspEnable()).WillOnce(Return(true));
396 
397     int32_t capabilities;
398     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
399     EXPECT_GT(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
400 }
401 
TEST_F(VibratorTest,supportsExternalControl_unsupported)402 TEST_F(VibratorTest, supportsExternalControl_unsupported) {
403     EXPECT_CALL(*mMockApi, hasEffectScale()).WillOnce(Return(true));
404     EXPECT_CALL(*mMockApi, hasAspEnable()).WillOnce(Return(false));
405 
406     int32_t capabilities;
407     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
408     EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
409 }
410 
TEST_F(VibratorTest,setExternalControl_enable)411 TEST_F(VibratorTest, setExternalControl_enable) {
412     Sequence s;
413 
414     EXPECT_CALL(*mMockApi, setGlobalScale(ON_GLOBAL_SCALE)).InSequence(s).WillOnce(Return(true));
415     EXPECT_CALL(*mMockApi, setAspEnable(true)).InSequence(s).WillOnce(Return(true));
416 
417     EXPECT_TRUE(mVibrator->setExternalControl(true).isOk());
418 }
419 
TEST_F(VibratorTest,setExternalControl_disable)420 TEST_F(VibratorTest, setExternalControl_disable) {
421     EXPECT_CALL(*mMockApi, setAspEnable(false)).WillOnce(Return(true));
422     EXPECT_CALL(*mMockApi, setGlobalScale(0)).WillOnce(Return(true));
423 
424     EXPECT_TRUE(mVibrator->setExternalControl(false).isOk());
425 }
426 
427 class EffectsTest : public VibratorTest, public WithParamInterface<EffectTuple> {
428   public:
PrintParam(const TestParamInfo<ParamType> & info)429     static auto PrintParam(const TestParamInfo<ParamType> &info) {
430         auto param = info.param;
431         auto effect = std::get<0>(param);
432         auto strength = std::get<1>(param);
433         return toString(effect) + "_" + toString(strength);
434     }
435 };
436 
TEST_P(EffectsTest,perform)437 TEST_P(EffectsTest, perform) {
438     auto param = GetParam();
439     auto effect = std::get<0>(param);
440     auto strength = std::get<1>(param);
441     auto scale = EFFECT_SCALE.find(param);
442     auto queue = EFFECT_QUEUE.find(param);
443     EffectDuration duration;
444     auto callback = ndk::SharedRefBase::make<MockVibratorCallback>();
445     std::promise<void> promise;
446     std::future<void> future{promise.get_future()};
447     auto complete = [&promise] {
448         promise.set_value();
449         return ndk::ScopedAStatus::ok();
450     };
451 
452     ExpectationSet eSetup;
453     Expectation eActivate, ePoll;
454 
455     if (scale != EFFECT_SCALE.end()) {
456         EffectIndex index = EFFECT_INDEX.at(effect);
457         duration = EFFECT_DURATIONS[index];
458 
459         eSetup += EXPECT_CALL(*mMockApi, setEffectIndex(index)).WillOnce(DoDefault());
460         eSetup += EXPECT_CALL(*mMockApi, setEffectScale(scale->second)).WillOnce(Return(true));
461     } else if (queue != EFFECT_QUEUE.end()) {
462         duration = std::get<1>(queue->second);
463 
464         eSetup += EXPECT_CALL(*mMockApi, setEffectIndex(QUEUE_INDEX)).WillOnce(DoDefault());
465         eSetup += EXPECT_CALL(*mMockApi, setEffectQueue(std::get<0>(queue->second)))
466                           .WillOnce(Return(true));
467         eSetup += EXPECT_CALL(*mMockApi, setEffectScale(0)).WillOnce(Return(true));
468     } else {
469         duration = 0;
470     }
471 
472     if (duration) {
473         eSetup += EXPECT_CALL(*mMockApi, setDuration(Ge(duration))).WillOnce(Return(true));
474         eActivate = EXPECT_CALL(*mMockApi, setActivate(true)).After(eSetup).WillOnce(Return(true));
475         ePoll = EXPECT_CALL(*mMockApi, pollVibeState(false))
476                         .After(eActivate)
477                         .WillOnce(Return(true));
478         EXPECT_CALL(*mMockApi, setActivate(false)).After(ePoll).WillOnce(Return(true));
479         EXPECT_CALL(*callback, onComplete()).After(ePoll).WillOnce(complete);
480     }
481 
482     int32_t lengthMs;
483     ndk::ScopedAStatus status = mVibrator->perform(effect, strength, callback, &lengthMs);
484     if (status.isOk()) {
485         EXPECT_LE(duration, lengthMs);
486     } else {
487         EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
488         EXPECT_EQ(0, lengthMs);
489     }
490 
491     if (duration) {
492         EXPECT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready);
493     }
494 }
495 
TEST_P(EffectsTest,alwaysOnEnable)496 TEST_P(EffectsTest, alwaysOnEnable) {
497     auto param = GetParam();
498     auto effect = std::get<0>(param);
499     auto strength = std::get<1>(param);
500     auto scale = EFFECT_SCALE.find(param);
501     bool supported = (scale != EFFECT_SCALE.end());
502 
503     if (supported) {
504         EXPECT_CALL(*mMockApi, setGpioRiseIndex(EFFECT_INDEX.at(effect))).WillOnce(Return(true));
505         EXPECT_CALL(*mMockApi, setGpioRiseScale(scale->second)).WillOnce(Return(true));
506     }
507 
508     ndk::ScopedAStatus status = mVibrator->alwaysOnEnable(0, effect, strength);
509     if (supported) {
510         EXPECT_EQ(EX_NONE, status.getExceptionCode());
511     } else {
512         EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
513     }
514 }
515 
516 const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
517                                    ndk::enum_range<Effect>().end()};
518 const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
519                                                    ndk::enum_range<EffectStrength>().end()};
520 
521 INSTANTIATE_TEST_CASE_P(VibratorTests, EffectsTest,
522                         Combine(ValuesIn(kEffects.begin(), kEffects.end()),
523                                 ValuesIn(kEffectStrengths.begin(), kEffectStrengths.end())),
524                         EffectsTest::PrintParam);
525 
526 struct PrimitiveParam {
527     CompositePrimitive primitive;
528     EffectIndex index;
529 };
530 
531 class PrimitiveTest : public VibratorTest, public WithParamInterface<PrimitiveParam> {
532   public:
PrintParam(const TestParamInfo<ParamType> & info)533     static auto PrintParam(const TestParamInfo<ParamType> &info) {
534         return toString(info.param.primitive);
535     }
536 };
537 
538 const std::vector<PrimitiveParam> kPrimitiveParams = {
539         {CompositePrimitive::NOOP, 0},       {CompositePrimitive::CLICK, 2},
540         {CompositePrimitive::THUD, 4},       {CompositePrimitive::SPIN, 5},
541         {CompositePrimitive::QUICK_RISE, 6}, {CompositePrimitive::SLOW_RISE, 7},
542         {CompositePrimitive::QUICK_FALL, 8},
543 };
544 
TEST_P(PrimitiveTest,getPrimitiveDuration)545 TEST_P(PrimitiveTest, getPrimitiveDuration) {
546     auto param = GetParam();
547     auto primitive = param.primitive;
548     auto index = param.index;
549     int32_t duration;
550 
551     EXPECT_EQ(EX_NONE, mVibrator->getPrimitiveDuration(primitive, &duration).getExceptionCode());
552     EXPECT_EQ(EFFECT_DURATIONS[index], duration);
553 }
554 
555 INSTANTIATE_TEST_CASE_P(VibratorTests, PrimitiveTest,
556                         ValuesIn(kPrimitiveParams.begin(), kPrimitiveParams.end()),
557                         PrimitiveTest::PrintParam);
558 
559 struct ComposeParam {
560     std::string name;
561     std::vector<CompositeEffect> composite;
562     EffectQueue queue;
563 };
564 
565 class ComposeTest : public VibratorTest, public WithParamInterface<ComposeParam> {
566   public:
PrintParam(const TestParamInfo<ParamType> & info)567     static auto PrintParam(const TestParamInfo<ParamType> &info) { return info.param.name; }
568 };
569 
TEST_P(ComposeTest,compose)570 TEST_P(ComposeTest, compose) {
571     auto param = GetParam();
572     auto composite = param.composite;
573     auto queue = std::get<0>(param.queue);
574     ExpectationSet eSetup;
575     Expectation eActivate, ePoll;
576     auto callback = ndk::SharedRefBase::make<MockVibratorCallback>();
577     std::promise<void> promise;
578     std::future<void> future{promise.get_future()};
579     auto complete = [&promise] {
580         promise.set_value();
581         return ndk::ScopedAStatus::ok();
582     };
583 
584     eSetup += EXPECT_CALL(*mMockApi, setEffectIndex(QUEUE_INDEX)).WillOnce(DoDefault());
585     eSetup += EXPECT_CALL(*mMockApi, setEffectQueue(queue)).WillOnce(Return(true));
586     eSetup += EXPECT_CALL(*mMockApi, setEffectScale(0)).WillOnce(Return(true));
587     eSetup += EXPECT_CALL(*mMockApi, setDuration(UINT32_MAX)).WillOnce(Return(true));
588     eActivate = EXPECT_CALL(*mMockApi, setActivate(true)).After(eSetup).WillOnce(Return(true));
589     ePoll = EXPECT_CALL(*mMockApi, pollVibeState(false)).After(eActivate).WillOnce(Return(true));
590     EXPECT_CALL(*mMockApi, setActivate(false)).After(ePoll).WillOnce(Return(true));
591     EXPECT_CALL(*callback, onComplete()).After(ePoll).WillOnce(complete);
592 
593     EXPECT_EQ(EX_NONE, mVibrator->compose(composite, callback).getExceptionCode());
594 
595     EXPECT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready);
596 }
597 
598 const std::vector<ComposeParam> kComposeParams = {
599         {"click", {{0, CompositePrimitive::CLICK, 1.0f}}, Queue(QueueEffect(2, Level(1.0f)), 0)},
600         {"thud", {{1, CompositePrimitive::THUD, 0.8f}}, Queue(1, QueueEffect(4, Level(0.8f)), 0)},
601         {"spin", {{2, CompositePrimitive::SPIN, 0.6f}}, Queue(2, QueueEffect(5, Level(0.6f)), 0)},
602         {"quick_rise",
603          {{3, CompositePrimitive::QUICK_RISE, 0.4f}},
604          Queue(3, QueueEffect(6, 0.4f * V_LEVELS[5]), 0)},
605         {"slow_rise",
606          {{4, CompositePrimitive::SLOW_RISE, 0.0f}},
607          Queue(4, QueueEffect(7, Level(0.0f)), 0)},
608         {"quick_fall",
609          {{5, CompositePrimitive::QUICK_FALL, 1.0f}},
610          Queue(5, QueueEffect(8, 1.0f * V_LEVELS[5]), 0)},
611         {"pop",
612          {{6, CompositePrimitive::SLOW_RISE, 1.0f}, {50, CompositePrimitive::THUD, 1.0f}},
613          Queue(6, QueueEffect(7, Level(1.0f)), 50, QueueEffect(4, Level(1.0f)), 0)},
614         {"snap",
615          {{7, CompositePrimitive::QUICK_RISE, 1.0f}, {0, CompositePrimitive::QUICK_FALL, 1.0f}},
616          Queue(7, QueueEffect(6, 1.0f * V_LEVELS[5]), QueueEffect(8, 1.0f * V_LEVELS[5]), 0)},
617 };
618 
619 INSTANTIATE_TEST_CASE_P(VibratorTests, ComposeTest,
620                         ValuesIn(kComposeParams.begin(), kComposeParams.end()),
621                         ComposeTest::PrintParam);
622 
623 class AlwaysOnTest : public VibratorTest, public WithParamInterface<int32_t> {
624   public:
PrintParam(const TestParamInfo<ParamType> & info)625     static auto PrintParam(const TestParamInfo<ParamType> &info) {
626         return std::to_string(info.param);
627     }
628 };
629 
TEST_P(AlwaysOnTest,alwaysOnEnable)630 TEST_P(AlwaysOnTest, alwaysOnEnable) {
631     auto param = GetParam();
632     auto scale = EFFECT_SCALE.begin();
633 
634     std::advance(scale, std::rand() % EFFECT_SCALE.size());
635 
636     auto effect = std::get<0>(scale->first);
637     auto strength = std::get<1>(scale->first);
638 
639     switch (param) {
640         case 0:
641             EXPECT_CALL(*mMockApi, setGpioRiseIndex(EFFECT_INDEX.at(effect)))
642                     .WillOnce(Return(true));
643             EXPECT_CALL(*mMockApi, setGpioRiseScale(scale->second)).WillOnce(Return(true));
644             break;
645         case 1:
646             EXPECT_CALL(*mMockApi, setGpioFallIndex(EFFECT_INDEX.at(effect)))
647                     .WillOnce(Return(true));
648             EXPECT_CALL(*mMockApi, setGpioFallScale(scale->second)).WillOnce(Return(true));
649             break;
650     }
651 
652     ndk::ScopedAStatus status = mVibrator->alwaysOnEnable(param, effect, strength);
653     EXPECT_EQ(EX_NONE, status.getExceptionCode());
654 }
655 
TEST_P(AlwaysOnTest,alwaysOnDisable)656 TEST_P(AlwaysOnTest, alwaysOnDisable) {
657     auto param = GetParam();
658 
659     switch (param) {
660         case 0:
661             EXPECT_CALL(*mMockApi, setGpioRiseIndex(0)).WillOnce(Return(true));
662             break;
663         case 1:
664             EXPECT_CALL(*mMockApi, setGpioFallIndex(0)).WillOnce(Return(true));
665             break;
666     }
667 
668     ndk::ScopedAStatus status = mVibrator->alwaysOnDisable(param);
669     EXPECT_EQ(EX_NONE, status.getExceptionCode());
670 }
671 
672 INSTANTIATE_TEST_CASE_P(VibratorTests, AlwaysOnTest, Range(0, 1), AlwaysOnTest::PrintParam);
673 
674 }  // namespace vibrator
675 }  // namespace hardware
676 }  // namespace android
677 }  // namespace aidl
678