1 /*
2 * Copyright (C) 2022 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 #include <linux/input.h>
22 #include <linux/uinput.h>
23
24 #include <future>
25
26 #include "Stats.h"
27 #include "Vibrator.h"
28 #include "mocks.h"
29 #include "types.h"
30 #include "utils.h"
31
32 namespace aidl {
33 namespace android {
34 namespace hardware {
35 namespace vibrator {
36
37 using ::testing::_;
38 using ::testing::AnyNumber;
39 using ::testing::Assign;
40 using ::testing::AtLeast;
41 using ::testing::AtMost;
42 using ::testing::Combine;
43 using ::testing::DoAll;
44 using ::testing::DoDefault;
45 using ::testing::Exactly;
46 using ::testing::Expectation;
47 using ::testing::ExpectationSet;
48 using ::testing::Ge;
49 using ::testing::Mock;
50 using ::testing::MockFunction;
51 using ::testing::Range;
52 using ::testing::Return;
53 using ::testing::Sequence;
54 using ::testing::SetArgPointee;
55 using ::testing::SetArgReferee;
56 using ::testing::Test;
57 using ::testing::TestParamInfo;
58 using ::testing::ValuesIn;
59 using ::testing::WithParamInterface;
60
61 // Forward Declarations
62
63 static EffectQueue Queue(const QueueEffect &effect);
64 static EffectQueue Queue(const QueueDelay &delay);
65 template <typename T, typename U, typename... Args>
66 static EffectQueue Queue(const T &first, const U &second, Args... rest);
67
68 static EffectLevel Level(float intensity, float levelLow, float levelHigh);
69 static EffectScale Scale(float intensity, float levelLow, float levelHigh);
70
71 // Constants With Arbitrary Values
72
73 static constexpr uint32_t CAL_VERSION = 2;
74 static constexpr std::array<EffectLevel, 2> V_TICK_DEFAULT = {1, 100};
75 static constexpr std::array<EffectLevel, 2> V_CLICK_DEFAULT{1, 100};
76 static constexpr std::array<EffectLevel, 2> V_LONG_DEFAULT{1, 100};
77 static constexpr std::array<EffectDuration, 14> EFFECT_DURATIONS{
78 0, 100, 12, 1000, 300, 133, 150, 500, 100, 5, 12, 1000, 1000, 1000};
79
80 // Constants With Prescribed Values
81
82 static const std::map<Effect, EffectIndex> EFFECT_INDEX{
83 {Effect::CLICK, 2},
84 {Effect::TICK, 2},
85 {Effect::HEAVY_CLICK, 2},
86 {Effect::TEXTURE_TICK, 9},
87 };
88 static constexpr uint32_t MIN_ON_OFF_INTERVAL_US = 8500;
89 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
90 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby
91 static constexpr auto POLLING_TIMEOUT = 50; // POLLING_TIMEOUT < ASYNC_COMPLETION_TIMEOUT
92 enum WaveformIndex : uint16_t {
93 /* Physical waveform */
94 WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
95 WAVEFORM_RESERVED_INDEX_1 = 1,
96 WAVEFORM_CLICK_INDEX = 2,
97 WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
98 WAVEFORM_THUD_INDEX = 4,
99 WAVEFORM_SPIN_INDEX = 5,
100 WAVEFORM_QUICK_RISE_INDEX = 6,
101 WAVEFORM_SLOW_RISE_INDEX = 7,
102 WAVEFORM_QUICK_FALL_INDEX = 8,
103 WAVEFORM_LIGHT_TICK_INDEX = 9,
104 WAVEFORM_LOW_TICK_INDEX = 10,
105 WAVEFORM_RESERVED_MFG_1,
106 WAVEFORM_RESERVED_MFG_2,
107 WAVEFORM_RESERVED_MFG_3,
108 WAVEFORM_MAX_PHYSICAL_INDEX,
109 /* OWT waveform */
110 WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
111 WAVEFORM_PWLE,
112 /*
113 * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
114 * #define FF_GAIN 0x60 // 96 in decimal
115 * #define FF_MAX_EFFECTS FF_GAIN
116 */
117 WAVEFORM_MAX_INDEX,
118 };
119
120 static const EffectScale ON_GLOBAL_SCALE{levelToScale(V_LONG_DEFAULT[1])};
121 static const EffectIndex ON_EFFECT_INDEX{0};
122
123 static const std::map<EffectTuple, EffectScale> EFFECT_SCALE{
124 {{Effect::TICK, EffectStrength::LIGHT},
125 Scale(0.5f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
126 {{Effect::TICK, EffectStrength::MEDIUM},
127 Scale(0.5f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
128 {{Effect::TICK, EffectStrength::STRONG},
129 Scale(0.5f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
130 {{Effect::CLICK, EffectStrength::LIGHT},
131 Scale(0.7f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
132 {{Effect::CLICK, EffectStrength::MEDIUM},
133 Scale(0.7f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
134 {{Effect::CLICK, EffectStrength::STRONG},
135 Scale(0.7f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
136 {{Effect::HEAVY_CLICK, EffectStrength::LIGHT},
137 Scale(1.0f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
138 {{Effect::HEAVY_CLICK, EffectStrength::MEDIUM},
139 Scale(1.0f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
140 {{Effect::HEAVY_CLICK, EffectStrength::STRONG},
141 Scale(1.0f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
142 {{Effect::TEXTURE_TICK, EffectStrength::LIGHT},
143 Scale(0.5f * 0.5f, V_TICK_DEFAULT[0], V_TICK_DEFAULT[1])},
144 {{Effect::TEXTURE_TICK, EffectStrength::MEDIUM},
145 Scale(0.5f * 0.7f, V_TICK_DEFAULT[0], V_TICK_DEFAULT[1])},
146 {{Effect::TEXTURE_TICK, EffectStrength::STRONG},
147 Scale(0.5f * 1.0f, V_TICK_DEFAULT[0], V_TICK_DEFAULT[1])},
148 };
149
150 static const std::map<EffectTuple, EffectQueue> EFFECT_QUEUE{
151 {{Effect::DOUBLE_CLICK, EffectStrength::LIGHT},
152 Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
153 Level(0.7f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
154 100,
155 QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
156 Level(1.0f * 0.5f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])})},
157 {{Effect::DOUBLE_CLICK, EffectStrength::MEDIUM},
158 Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
159 Level(0.7f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
160 100,
161 QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
162 Level(1.0f * 0.7f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])})},
163 {{Effect::DOUBLE_CLICK, EffectStrength::STRONG},
164 Queue(QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
165 Level(0.7f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])},
166 100,
167 QueueEffect{EFFECT_INDEX.at(Effect::CLICK),
168 Level(1.0f * 1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])})},
169 };
170
Queue(const QueueEffect & effect)171 EffectQueue Queue(const QueueEffect &effect) {
172 auto index = std::get<0>(effect);
173 auto level = std::get<1>(effect);
174 auto string = std::to_string(index) + "." + std::to_string(level);
175 auto duration = EFFECT_DURATIONS[index];
176 return {string, duration};
177 }
178
Queue(const QueueDelay & delay)179 EffectQueue Queue(const QueueDelay &delay) {
180 auto string = std::to_string(delay);
181 return {string, delay};
182 }
183
184 template <typename T, typename U, typename... Args>
Queue(const T & first,const U & second,Args...rest)185 EffectQueue Queue(const T &first, const U &second, Args... rest) {
186 auto head = Queue(first);
187 auto tail = Queue(second, rest...);
188 auto string = std::get<0>(head) + "," + std::get<0>(tail);
189 auto duration = std::get<1>(head) + std::get<1>(tail);
190 return {string, duration};
191 }
192
Level(float intensity,float levelLow,float levelHigh)193 static EffectLevel Level(float intensity, float levelLow, float levelHigh) {
194 return std::lround(intensity * (levelHigh - levelLow)) + levelLow;
195 }
196
Scale(float intensity,float levelLow,float levelHigh)197 static EffectScale Scale(float intensity, float levelLow, float levelHigh) {
198 return levelToScale(Level(intensity, levelLow, levelHigh));
199 }
200
201 class VibratorTest : public Test {
202 public:
SetUp()203 void SetUp() override {
204 setenv("INPUT_EVENT_NAME", "CS40L26TestSuite", true);
205 std::unique_ptr<MockApi> mockapi;
206 std::unique_ptr<MockCal> mockcal;
207 std::unique_ptr<MockStats> mockstats;
208
209 createMock(&mockapi, &mockcal, &mockstats);
210 createVibrator(std::move(mockapi), std::move(mockcal), std::move(mockstats));
211 }
212
TearDown()213 void TearDown() override { deleteVibrator(); }
214
215 protected:
createMock(std::unique_ptr<MockApi> * mockapi,std::unique_ptr<MockCal> * mockcal,std::unique_ptr<MockStats> * mockstats)216 void createMock(std::unique_ptr<MockApi> *mockapi, std::unique_ptr<MockCal> *mockcal,
217 std::unique_ptr<MockStats> *mockstats) {
218 *mockapi = std::make_unique<MockApi>();
219 *mockcal = std::make_unique<MockCal>();
220 *mockstats = std::make_unique<MockStats>();
221
222 mMockApi = mockapi->get();
223 mMockCal = mockcal->get();
224 mMockStats = mockstats->get();
225
226 ON_CALL(*mMockApi, destructor()).WillByDefault(Assign(&mMockApi, nullptr));
227
228 ON_CALL(*mMockApi, initFF()).WillByDefault(Return(false));
229 ON_CALL(*mMockApi, setFFGain(_)).WillByDefault(Return(true));
230 ON_CALL(*mMockApi, setFFEffect(_, _)).WillByDefault(Return(true));
231 ON_CALL(*mMockApi, setFFPlay(_, _)).WillByDefault(Return(true));
232 ON_CALL(*mMockApi, pollVibeState(_, _)).WillByDefault(Return(true));
233 ON_CALL(*mMockApi, uploadOwtEffect(_, _, _, _, _)).WillByDefault(Return(true));
234 ON_CALL(*mMockApi, eraseOwtEffect(_, _)).WillByDefault(Return(true));
235
236 ON_CALL(*mMockApi, getOwtFreeSpace(_))
237 .WillByDefault(DoAll(SetArgPointee<0>(11504), Return(true)));
238
239 ON_CALL(*mMockCal, destructor()).WillByDefault(Assign(&mMockCal, nullptr));
240
241 ON_CALL(*mMockCal, getVersion(_))
242 .WillByDefault(DoAll(SetArgPointee<0>(CAL_VERSION), Return(true)));
243
244 ON_CALL(*mMockCal, getTickVolLevels(_))
245 .WillByDefault(DoAll(SetArgPointee<0>(V_TICK_DEFAULT), Return(true)));
246 ON_CALL(*mMockCal, getClickVolLevels(_))
247 .WillByDefault(DoAll(SetArgPointee<0>(V_CLICK_DEFAULT), Return(true)));
248 ON_CALL(*mMockCal, getLongVolLevels(_))
249 .WillByDefault(DoAll(SetArgPointee<0>(V_LONG_DEFAULT), Return(true)));
250
251 ON_CALL(*mMockStats, destructor()).WillByDefault(Assign(&mMockStats, nullptr));
252 ON_CALL(*mMockStats, logPrimitive(_)).WillByDefault(Return(true));
253 ON_CALL(*mMockStats, logWaveform(_, _)).WillByDefault(Return(true));
254 ON_CALL(*mMockStats, logLatencyStart(_)).WillByDefault(Return(true));
255 ON_CALL(*mMockStats, logLatencyEnd()).WillByDefault(Return(true));
256
257 relaxMock(false);
258 }
259
createVibrator(std::unique_ptr<MockApi> mockapi,std::unique_ptr<MockCal> mockcal,std::unique_ptr<MockStats> mockstats,bool relaxed=true)260 void createVibrator(std::unique_ptr<MockApi> mockapi, std::unique_ptr<MockCal> mockcal,
261 std::unique_ptr<MockStats> mockstats, bool relaxed = true) {
262 if (relaxed) {
263 relaxMock(true);
264 }
265 mVibrator = ndk::SharedRefBase::make<Vibrator>(std::move(mockapi), std::move(mockcal),
266 std::move(mockstats));
267 if (relaxed) {
268 relaxMock(false);
269 }
270 }
271
deleteVibrator(bool relaxed=true)272 void deleteVibrator(bool relaxed = true) {
273 if (relaxed) {
274 relaxMock(true);
275 }
276 mVibrator.reset();
277 }
278
279 private:
relaxMock(bool relax)280 void relaxMock(bool relax) {
281 auto times = relax ? AnyNumber() : Exactly(0);
282
283 Mock::VerifyAndClearExpectations(mMockApi);
284 Mock::VerifyAndClearExpectations(mMockCal);
285 Mock::VerifyAndClearExpectations(mMockStats);
286
287 EXPECT_CALL(*mMockApi, destructor()).Times(times);
288 EXPECT_CALL(*mMockApi, setF0(_)).Times(times);
289 EXPECT_CALL(*mMockApi, setF0Offset(_)).Times(times);
290 EXPECT_CALL(*mMockApi, setRedc(_)).Times(times);
291 EXPECT_CALL(*mMockApi, setQ(_)).Times(times);
292 EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).Times(times);
293 EXPECT_CALL(*mMockApi, getOwtFreeSpace(_)).Times(times);
294 EXPECT_CALL(*mMockApi, setF0CompEnable(_)).Times(times);
295 EXPECT_CALL(*mMockApi, setRedcCompEnable(_)).Times(times);
296 EXPECT_CALL(*mMockApi, pollVibeState(_, _)).Times(times);
297 EXPECT_CALL(*mMockApi, initFF()).Times(times);
298 EXPECT_CALL(*mMockApi, setFFGain(_)).Times(times);
299 EXPECT_CALL(*mMockApi, setFFEffect(_, _)).Times(times);
300 EXPECT_CALL(*mMockApi, setFFPlay(_, _)).Times(times);
301 EXPECT_CALL(*mMockApi, uploadOwtEffect(_, _, _, _, _)).Times(times);
302 EXPECT_CALL(*mMockApi, eraseOwtEffect(_, _)).Times(times);
303 EXPECT_CALL(*mMockApi, setMinOnOffInterval(_)).Times(times);
304 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).Times(times);
305 EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, _, _, _)).Times(times);
306 EXPECT_CALL(*mMockApi, isPassthroughI2sHapticSupported()).Times(times);
307 EXPECT_CALL(*mMockApi, enableDbc()).Times(times);
308
309 EXPECT_CALL(*mMockApi, debug(_)).Times(times);
310
311 EXPECT_CALL(*mMockCal, destructor()).Times(times);
312 EXPECT_CALL(*mMockCal, getF0(_)).Times(times);
313 EXPECT_CALL(*mMockCal, getRedc(_)).Times(times);
314 EXPECT_CALL(*mMockCal, getQ(_)).Times(times);
315 EXPECT_CALL(*mMockCal, getTickVolLevels(_)).Times(times);
316 EXPECT_CALL(*mMockCal, getClickVolLevels(_)).Times(times);
317 EXPECT_CALL(*mMockCal, getLongVolLevels(_)).Times(times);
318 EXPECT_CALL(*mMockCal, isChirpEnabled()).Times(times);
319 EXPECT_CALL(*mMockCal, getLongFrequencyShift(_)).Times(times);
320 EXPECT_CALL(*mMockCal, isF0CompEnabled()).Times(times);
321 EXPECT_CALL(*mMockCal, isRedcCompEnabled()).Times(times);
322 EXPECT_CALL(*mMockCal, debug(_)).Times(times);
323
324 EXPECT_CALL(*mMockStats, destructor()).Times(times);
325 EXPECT_CALL(*mMockStats, logPrimitive(_)).Times(times);
326 EXPECT_CALL(*mMockStats, logWaveform(_, _)).Times(times);
327 EXPECT_CALL(*mMockStats, logLatencyStart(_)).Times(times);
328 EXPECT_CALL(*mMockStats, logLatencyEnd()).Times(times);
329 }
330
331 protected:
332 MockApi *mMockApi;
333 MockCal *mMockCal;
334 MockStats *mMockStats;
335 std::shared_ptr<IVibrator> mVibrator;
336 uint32_t mEffectIndex;
337 };
338
TEST_F(VibratorTest,Constructor)339 TEST_F(VibratorTest, Constructor) {
340 std::unique_ptr<MockApi> mockapi;
341 std::unique_ptr<MockCal> mockcal;
342 std::unique_ptr<MockStats> mockstats;
343 int min_val = 0xC8000;
344 int max_val = 0x7FC000;
345 std::string f0Val = std::to_string(std::rand() % (max_val - min_val + 1) + min_val);
346 std::string redcVal = std::to_string(std::rand() % (max_val - min_val + 1) + min_val);
347 std::string qVal = std::to_string(std::rand() % (max_val - min_val + 1) + min_val);
348 uint32_t calVer;
349 uint32_t supportedPrimitivesBits = 0x0;
350 Expectation volGet;
351 Sequence f0Seq, redcSeq, qSeq, supportedPrimitivesSeq;
352
353 EXPECT_CALL(*mMockApi, destructor()).WillOnce(DoDefault());
354 EXPECT_CALL(*mMockCal, destructor()).WillOnce(DoDefault());
355 EXPECT_CALL(*mMockStats, destructor()).WillOnce(DoDefault());
356
357 deleteVibrator(false);
358
359 createMock(&mockapi, &mockcal, &mockstats);
360
361 EXPECT_CALL(*mMockCal, getF0(_))
362 .InSequence(f0Seq)
363 .WillOnce(DoAll(SetArgReferee<0>(f0Val), Return(true)));
364 EXPECT_CALL(*mMockApi, setF0(f0Val)).InSequence(f0Seq).WillOnce(Return(true));
365
366 EXPECT_CALL(*mMockCal, getRedc(_))
367 .InSequence(redcSeq)
368 .WillOnce(DoAll(SetArgReferee<0>(redcVal), Return(true)));
369 EXPECT_CALL(*mMockApi, setRedc(redcVal)).InSequence(redcSeq).WillOnce(Return(true));
370
371 EXPECT_CALL(*mMockCal, getQ(_))
372 .InSequence(qSeq)
373 .WillOnce(DoAll(SetArgReferee<0>(qVal), Return(true)));
374 EXPECT_CALL(*mMockApi, setQ(qVal)).InSequence(qSeq).WillOnce(Return(true));
375
376 EXPECT_CALL(*mMockCal, getLongFrequencyShift(_)).WillOnce(Return(true));
377
378 mMockCal->getVersion(&calVer);
379 if (calVer == 2) {
380 volGet = EXPECT_CALL(*mMockCal, getTickVolLevels(_)).WillOnce(DoDefault());
381 volGet = EXPECT_CALL(*mMockCal, getClickVolLevels(_)).WillOnce(DoDefault());
382 volGet = EXPECT_CALL(*mMockCal, getLongVolLevels(_)).WillOnce(DoDefault());
383 }
384
385 EXPECT_CALL(*mMockCal, isF0CompEnabled()).WillOnce(Return(true));
386 EXPECT_CALL(*mMockApi, setF0CompEnable(true)).WillOnce(Return(true));
387 EXPECT_CALL(*mMockCal, isRedcCompEnabled()).WillOnce(Return(true));
388 EXPECT_CALL(*mMockApi, setRedcCompEnable(true)).WillOnce(Return(true));
389
390 EXPECT_CALL(*mMockApi, isPassthroughI2sHapticSupported()).WillOnce(Return(false));
391 EXPECT_CALL(*mMockCal, isChirpEnabled()).WillOnce(Return(true));
392 EXPECT_CALL(*mMockCal, getSupportedPrimitives(_))
393 .InSequence(supportedPrimitivesSeq)
394 .WillOnce(DoAll(SetArgPointee<0>(supportedPrimitivesBits), Return(true)));
395
396 EXPECT_CALL(*mMockApi, setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US)).WillOnce(Return(true));
397 EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
398 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(true));
399 EXPECT_CALL(*mMockApi, getContextScale()).WillRepeatedly(Return(0));
400 EXPECT_CALL(*mMockApi, getContextEnable()).WillRepeatedly(Return(false));
401 EXPECT_CALL(*mMockApi, getContextSettlingTime()).WillRepeatedly(Return(0));
402 EXPECT_CALL(*mMockApi, getContextCooldownTime()).WillRepeatedly(Return(0));
403 EXPECT_CALL(*mMockApi, getContextFadeEnable()).WillRepeatedly(Return(false));
404 EXPECT_CALL(*mMockApi, enableDbc()).WillOnce(Return(true));
405 createVibrator(std::move(mockapi), std::move(mockcal), std::move(mockstats), false);
406 }
407
TEST_F(VibratorTest,on)408 TEST_F(VibratorTest, on) {
409 Sequence s1, s2;
410 uint16_t duration = std::rand() + 1;
411
412 EXPECT_CALL(*mMockStats, logLatencyStart(kWaveformEffectLatency))
413 .InSequence(s1, s2)
414 .WillOnce(DoDefault());
415 EXPECT_CALL(*mMockApi, setFFGain(ON_GLOBAL_SCALE)).InSequence(s1).WillOnce(DoDefault());
416 EXPECT_CALL(*mMockStats, logWaveform(_, _)).InSequence(s1).WillOnce(DoDefault());
417 EXPECT_CALL(*mMockApi, setFFEffect(_, duration + MAX_COLD_START_LATENCY_MS))
418 .InSequence(s2)
419 .WillOnce(DoDefault());
420 EXPECT_CALL(*mMockStats, logLatencyEnd()).InSequence(s1, s2).WillOnce(DoDefault());
421 EXPECT_CALL(*mMockApi, setFFPlay(ON_EFFECT_INDEX, true))
422 .InSequence(s1, s2)
423 .WillOnce(DoDefault());
424 EXPECT_TRUE(mVibrator->on(duration, nullptr).isOk());
425 }
426
TEST_F(VibratorTest,off)427 TEST_F(VibratorTest, off) {
428 Sequence s1;
429 EXPECT_CALL(*mMockApi, setFFGain(ON_GLOBAL_SCALE)).InSequence(s1).WillOnce(DoDefault());
430 EXPECT_TRUE(mVibrator->off().isOk());
431 }
432
TEST_F(VibratorTest,supportsAmplitudeControl_supported)433 TEST_F(VibratorTest, supportsAmplitudeControl_supported) {
434 int32_t capabilities;
435 EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
436 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(true));
437
438 EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
439 EXPECT_GT(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
440 }
441
TEST_F(VibratorTest,supportsExternalAmplitudeControl_unsupported)442 TEST_F(VibratorTest, supportsExternalAmplitudeControl_unsupported) {
443 int32_t capabilities;
444 EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
445 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(true));
446
447 EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
448 EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL, 0);
449 }
450
TEST_F(VibratorTest,setAmplitude_supported)451 TEST_F(VibratorTest, setAmplitude_supported) {
452 EffectAmplitude amplitude = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
453
454 EXPECT_CALL(*mMockApi, setFFGain(amplitudeToScale(amplitude))).WillOnce(Return(true));
455
456 EXPECT_TRUE(mVibrator->setAmplitude(amplitude).isOk());
457 }
458
TEST_F(VibratorTest,supportsExternalControl_supported)459 TEST_F(VibratorTest, supportsExternalControl_supported) {
460 int32_t capabilities;
461 EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
462 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(true));
463
464 EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
465 EXPECT_GT(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
466 }
467
TEST_F(VibratorTest,supportsExternalControl_unsupported)468 TEST_F(VibratorTest, supportsExternalControl_unsupported) {
469 int32_t capabilities;
470 EXPECT_CALL(*mMockApi, hasOwtFreeSpace()).WillOnce(Return(true));
471 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).WillOnce(Return(false));
472
473 EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
474 EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
475 }
476
TEST_F(VibratorTest,setExternalControl_enable)477 TEST_F(VibratorTest, setExternalControl_enable) {
478 Sequence s1, s2;
479 EXPECT_CALL(*mMockApi, setFFGain(ON_GLOBAL_SCALE)).InSequence(s1).WillOnce(DoDefault());
480 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).InSequence(s2).WillOnce(Return(true));
481 EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, true, _, _))
482 .InSequence(s1, s2)
483 .WillOnce(Return(true));
484
485 EXPECT_TRUE(mVibrator->setExternalControl(true).isOk());
486 }
487
TEST_F(VibratorTest,setExternalControl_disable)488 TEST_F(VibratorTest, setExternalControl_disable) {
489 Sequence s1, s2, s3, s4;
490
491 // The default mIsUnderExternalControl is false, so it needs to turn on the External Control
492 // to make mIsUnderExternalControl become true.
493 EXPECT_CALL(*mMockApi, setFFGain(ON_GLOBAL_SCALE))
494 .InSequence(s1)
495 .InSequence(s1)
496 .WillOnce(DoDefault());
497 EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).InSequence(s2).WillOnce(Return(true));
498 EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, true, _, _)).InSequence(s3).WillOnce(Return(true));
499
500 EXPECT_TRUE(mVibrator->setExternalControl(true).isOk());
501
502 EXPECT_CALL(*mMockApi, setFFGain(levelToScale(VOLTAGE_SCALE_MAX)))
503 .InSequence(s4)
504 .WillOnce(DoDefault());
505 EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, false, _, _))
506 .InSequence(s1, s2, s3, s4)
507 .WillOnce(Return(true));
508
509 EXPECT_TRUE(mVibrator->setExternalControl(false).isOk());
510 }
511
512 class EffectsTest : public VibratorTest, public WithParamInterface<EffectTuple> {
513 public:
PrintParam(const TestParamInfo<ParamType> & info)514 static auto PrintParam(const TestParamInfo<ParamType> &info) {
515 auto param = info.param;
516 auto effect = std::get<0>(param);
517 auto strength = std::get<1>(param);
518 return toString(effect) + "_" + toString(strength);
519 }
520 };
521
TEST_P(EffectsTest,perform)522 TEST_P(EffectsTest, perform) {
523 auto param = GetParam();
524 auto effect = std::get<0>(param);
525 auto strength = std::get<1>(param);
526 auto scale = EFFECT_SCALE.find(param);
527 auto queue = EFFECT_QUEUE.find(param);
528 EffectDuration duration;
529 auto callback = ndk::SharedRefBase::make<MockVibratorCallback>();
530 std::promise<void> promise;
531 std::future<void> future{promise.get_future()};
532 auto complete = [&promise] {
533 promise.set_value();
534 return ndk::ScopedAStatus::ok();
535 };
536 bool composeEffect;
537
538 ExpectationSet eSetup;
539 Expectation eActivate, ePollHaptics, ePollStop, eEraseDone;
540
541 eSetup +=
542 EXPECT_CALL(*mMockStats, logLatencyStart(kPrebakedEffectLatency)).WillOnce(DoDefault());
543
544 if (scale != EFFECT_SCALE.end()) {
545 EffectIndex index = EFFECT_INDEX.at(effect);
546 duration = EFFECT_DURATIONS[index];
547
548 eSetup += EXPECT_CALL(*mMockApi, setFFGain(levelToScale(scale->second)))
549 .WillOnce(DoDefault());
550 eSetup += EXPECT_CALL(*mMockStats, logLatencyEnd()).WillOnce(DoDefault());
551 eActivate =
552 EXPECT_CALL(*mMockApi, setFFPlay(index, true)).After(eSetup).WillOnce(DoDefault());
553 } else if (queue != EFFECT_QUEUE.end()) {
554 duration = std::get<1>(queue->second);
555 eSetup += EXPECT_CALL(*mMockApi, setFFGain(ON_GLOBAL_SCALE))
556 .After(eSetup)
557 .WillOnce(DoDefault());
558 eSetup += EXPECT_CALL(*mMockApi, getOwtFreeSpace(_)).WillOnce(DoDefault());
559 eSetup += EXPECT_CALL(*mMockApi, uploadOwtEffect(_, _, _, _, _))
560 .After(eSetup)
561 .WillOnce(DoDefault());
562 eSetup += EXPECT_CALL(*mMockStats, logLatencyEnd()).After(eSetup).WillOnce(DoDefault());
563 eActivate = EXPECT_CALL(*mMockApi, setFFPlay(WAVEFORM_COMPOSE, true))
564 .After(eSetup)
565 .WillOnce(DoDefault());
566 composeEffect = true;
567 } else {
568 duration = 0;
569 }
570
571 if (duration) {
572 ePollHaptics = EXPECT_CALL(*mMockApi, pollVibeState(1, POLLING_TIMEOUT))
573 .After(eActivate)
574 .WillOnce(DoDefault());
575 ePollStop = EXPECT_CALL(*mMockApi, pollVibeState(0, -1))
576 .After(ePollHaptics)
577 .WillOnce(DoDefault());
578 if (composeEffect) {
579 eEraseDone = EXPECT_CALL(*mMockApi, eraseOwtEffect(_, _))
580 .After(ePollStop)
581 .WillOnce(DoDefault());
582 EXPECT_CALL(*callback, onComplete()).After(eEraseDone).WillOnce(complete);
583 } else {
584 EXPECT_CALL(*callback, onComplete()).After(ePollStop).WillOnce(complete);
585 }
586 }
587
588 int32_t lengthMs;
589 ndk::ScopedAStatus status = mVibrator->perform(effect, strength, callback, &lengthMs);
590 if (status.isOk()) {
591 EXPECT_LE(duration, lengthMs);
592 } else {
593 EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
594 EXPECT_EQ(0, lengthMs);
595 }
596
597 if (duration) {
598 EXPECT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready);
599 }
600 }
601
602 const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
603 ndk::enum_range<Effect>().end()};
604 const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
605 ndk::enum_range<EffectStrength>().end()};
606
607 INSTANTIATE_TEST_CASE_P(VibratorTests, EffectsTest,
608 Combine(ValuesIn(kEffects.begin(), kEffects.end()),
609 ValuesIn(kEffectStrengths.begin(), kEffectStrengths.end())),
610 EffectsTest::PrintParam);
611
612 struct PrimitiveParam {
613 CompositePrimitive primitive;
614 EffectIndex index;
615 };
616
617 class PrimitiveTest : public VibratorTest, public WithParamInterface<PrimitiveParam> {
618 public:
PrintParam(const TestParamInfo<ParamType> & info)619 static auto PrintParam(const TestParamInfo<ParamType> &info) {
620 return toString(info.param.primitive);
621 }
622 };
623
624 const std::vector<PrimitiveParam> kPrimitiveParams = {
625 {CompositePrimitive::CLICK, 2}, {CompositePrimitive::THUD, 4},
626 {CompositePrimitive::SPIN, 5}, {CompositePrimitive::QUICK_RISE, 6},
627 {CompositePrimitive::SLOW_RISE, 7}, {CompositePrimitive::QUICK_FALL, 8},
628 {CompositePrimitive::LIGHT_TICK, 9}, {CompositePrimitive::LOW_TICK, 10},
629 };
630
TEST_P(PrimitiveTest,getPrimitiveDuration)631 TEST_P(PrimitiveTest, getPrimitiveDuration) {
632 auto param = GetParam();
633 auto primitive = param.primitive;
634 auto index = param.index;
635 int32_t duration;
636
637 EXPECT_EQ(EX_NONE, mVibrator->getPrimitiveDuration(primitive, &duration).getExceptionCode());
638 EXPECT_EQ(EFFECT_DURATIONS[index], duration);
639 }
640
641 INSTANTIATE_TEST_CASE_P(VibratorTests, PrimitiveTest,
642 ValuesIn(kPrimitiveParams.begin(), kPrimitiveParams.end()),
643 PrimitiveTest::PrintParam);
644
645 struct ComposeParam {
646 std::string name;
647 std::vector<CompositeEffect> composite;
648 EffectQueue queue;
649 };
650
651 class ComposeTest : public VibratorTest, public WithParamInterface<ComposeParam> {
652 public:
PrintParam(const TestParamInfo<ParamType> & info)653 static auto PrintParam(const TestParamInfo<ParamType> &info) { return info.param.name; }
654 };
655
TEST_P(ComposeTest,compose)656 TEST_P(ComposeTest, compose) {
657 auto param = GetParam();
658 auto composite = param.composite;
659 auto queue = std::get<0>(param.queue);
660 ExpectationSet eSetup;
661 Expectation eActivate, ePollHaptics, ePollStop, eEraseDone;
662 auto callback = ndk::SharedRefBase::make<MockVibratorCallback>();
663 std::promise<void> promise;
664 std::future<void> future{promise.get_future()};
665 auto complete = [&promise] {
666 promise.set_value();
667 return ndk::ScopedAStatus::ok();
668 };
669
670 eSetup += EXPECT_CALL(*mMockStats, logLatencyStart(kCompositionEffectLatency))
671 .WillOnce(DoDefault());
672 for (auto &primitive : composite) {
673 eSetup += EXPECT_CALL(*mMockStats, logPrimitive(_)).After(eSetup).WillOnce(DoDefault());
674 }
675 eSetup +=
676 EXPECT_CALL(*mMockApi, setFFGain(ON_GLOBAL_SCALE)).After(eSetup).WillOnce(DoDefault());
677 eSetup += EXPECT_CALL(*mMockApi, getOwtFreeSpace(_)).WillOnce(DoDefault());
678 eSetup += EXPECT_CALL(*mMockApi, uploadOwtEffect(_, _, _, _, _))
679 .After(eSetup)
680 .WillOnce(DoDefault());
681 eSetup += EXPECT_CALL(*mMockStats, logLatencyEnd()).WillOnce(DoDefault());
682 eActivate = EXPECT_CALL(*mMockApi, setFFPlay(WAVEFORM_COMPOSE, true))
683 .After(eSetup)
684 .WillOnce(DoDefault());
685
686 ePollHaptics = EXPECT_CALL(*mMockApi, pollVibeState(1, POLLING_TIMEOUT))
687 .After(eActivate)
688 .WillOnce(DoDefault());
689 ePollStop =
690 EXPECT_CALL(*mMockApi, pollVibeState(0, -1)).After(ePollHaptics).WillOnce(DoDefault());
691 eEraseDone =
692 EXPECT_CALL(*mMockApi, eraseOwtEffect(_, _)).After(ePollStop).WillOnce(DoDefault());
693 EXPECT_CALL(*callback, onComplete()).After(eEraseDone).WillOnce(complete);
694
695 EXPECT_EQ(EX_NONE, mVibrator->compose(composite, callback).getExceptionCode());
696
697 EXPECT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready);
698 }
699
700 const std::vector<ComposeParam> kComposeParams = {
701 {"click",
702 {{0, CompositePrimitive::CLICK, 1.0f}},
703 Queue(QueueEffect(2, Level(1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
704 {"thud",
705 {{1, CompositePrimitive::THUD, 0.8f}},
706 Queue(1, QueueEffect(4, Level(0.8f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
707 {"spin",
708 {{2, CompositePrimitive::SPIN, 0.6f}},
709 Queue(2, QueueEffect(5, Level(0.6f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
710 {"quick_rise",
711 {{3, CompositePrimitive::QUICK_RISE, 0.4f}},
712 Queue(3, QueueEffect(6, Level(0.4f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])), 0)},
713 {"slow_rise",
714 {{4, CompositePrimitive::SLOW_RISE, 0.0f}},
715 Queue(4, QueueEffect(7, Level(0.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
716 {"quick_fall",
717 {{5, CompositePrimitive::QUICK_FALL, 1.0f}},
718 Queue(5, QueueEffect(8, Level(1.0f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])), 0)},
719 {"pop",
720 {{6, CompositePrimitive::SLOW_RISE, 1.0f}, {50, CompositePrimitive::THUD, 1.0f}},
721 Queue(6, QueueEffect(7, Level(1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 50,
722 QueueEffect(4, Level(1.0f, V_CLICK_DEFAULT[0], V_CLICK_DEFAULT[1])), 0)},
723 {"snap",
724 {{7, CompositePrimitive::QUICK_RISE, 1.0f}, {0, CompositePrimitive::QUICK_FALL, 1.0f}},
725 Queue(7, QueueEffect(6, Level(1.0f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])),
726 QueueEffect(8, Level(1.0f, V_LONG_DEFAULT[0], V_LONG_DEFAULT[1])), 0)},
727 };
728
729 INSTANTIATE_TEST_CASE_P(VibratorTests, ComposeTest,
730 ValuesIn(kComposeParams.begin(), kComposeParams.end()),
731 ComposeTest::PrintParam);
732 } // namespace vibrator
733 } // namespace hardware
734 } // namespace android
735 } // namespace aidl
736