1 /*
2 * Copyright (C) 2020 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 #define LOG_TAG "VibratorHalWrapperAidlTest"
18
19 #include <aidl/android/hardware/vibrator/IVibrator.h>
20 #include <android/persistable_bundle_aidl.h>
21
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24
25 #include <utils/Log.h>
26 #include <thread>
27
28 #include <vibratorservice/VibratorCallbackScheduler.h>
29 #include <vibratorservice/VibratorHalWrapper.h>
30
31 #include "test_mocks.h"
32 #include "test_utils.h"
33
34 using aidl::android::hardware::vibrator::Braking;
35 using aidl::android::hardware::vibrator::CompositeEffect;
36 using aidl::android::hardware::vibrator::CompositePrimitive;
37 using aidl::android::hardware::vibrator::CompositePwleV2;
38 using aidl::android::hardware::vibrator::Effect;
39 using aidl::android::hardware::vibrator::EffectStrength;
40 using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
41 using aidl::android::hardware::vibrator::IVibrator;
42 using aidl::android::hardware::vibrator::IVibratorCallback;
43 using aidl::android::hardware::vibrator::PrimitivePwle;
44 using aidl::android::hardware::vibrator::PwleV2Primitive;
45 using aidl::android::hardware::vibrator::VendorEffect;
46 using aidl::android::os::PersistableBundle;
47
48 using namespace android;
49 using namespace std::chrono_literals;
50 using namespace testing;
51
52 // -------------------------------------------------------------------------------------------------
53
54 class VibratorHalWrapperAidlTest : public Test {
55 public:
SetUp()56 void SetUp() override {
57 mMockHal = ndk::SharedRefBase::make<StrictMock<vibrator::MockIVibrator>>();
58 mMockScheduler = std::make_shared<StrictMock<vibrator::MockCallbackScheduler>>();
59 mWrapper = std::make_unique<vibrator::AidlHalWrapper>(mMockScheduler, mMockHal);
60 ASSERT_NE(mWrapper, nullptr);
61 }
62
63 protected:
64 std::shared_ptr<StrictMock<vibrator::MockCallbackScheduler>> mMockScheduler = nullptr;
65 std::unique_ptr<vibrator::HalWrapper> mWrapper = nullptr;
66 std::shared_ptr<StrictMock<vibrator::MockIVibrator>> mMockHal = nullptr;
67 };
68
69 // -------------------------------------------------------------------------------------------------
70
TEST_F(VibratorHalWrapperAidlTest,TestOnWithCallbackSupport)71 TEST_F(VibratorHalWrapperAidlTest, TestOnWithCallbackSupport) {
72 {
73 InSequence seq;
74 EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
75 .Times(Exactly(1))
76 .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK),
77 Return(ndk::ScopedAStatus::ok())));
78 EXPECT_CALL(*mMockHal.get(), on(Eq(10), _))
79 .Times(Exactly(1))
80 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
81 Return(ndk::ScopedAStatus::ok())));
82 EXPECT_CALL(*mMockHal.get(), on(Eq(100), _))
83 .Times(Exactly(1))
84 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
85 EXPECT_CALL(*mMockHal.get(), on(Eq(1000), _))
86 .Times(Exactly(1))
87 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
88 }
89
90 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
91 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
92
93 ASSERT_TRUE(mWrapper->on(10ms, callback).isOk());
94 ASSERT_EQ(1, *callbackCounter.get());
95
96 ASSERT_TRUE(mWrapper->on(100ms, callback).isUnsupported());
97 // Callback not triggered for unsupported
98 ASSERT_EQ(1, *callbackCounter.get());
99
100 ASSERT_TRUE(mWrapper->on(1000ms, callback).isFailed());
101 // Callback not triggered on failure
102 ASSERT_EQ(1, *callbackCounter.get());
103 }
104
TEST_F(VibratorHalWrapperAidlTest,TestOnWithoutCallbackSupport)105 TEST_F(VibratorHalWrapperAidlTest, TestOnWithoutCallbackSupport) {
106 {
107 InSequence seq;
108 EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
109 .Times(Exactly(1))
110 .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_COMPOSE_EFFECTS),
111 Return(ndk::ScopedAStatus::ok())));
112 EXPECT_CALL(*mMockHal.get(), on(Eq(10), _))
113 .Times(Exactly(1))
114 .WillOnce(Return(ndk::ScopedAStatus::ok()));
115 EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms)))
116 .Times(Exactly(1))
117 .WillOnce(vibrator::TriggerSchedulerCallback());
118 EXPECT_CALL(*mMockHal.get(), on(Eq(11), _))
119 .Times(Exactly(1))
120 .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)));
121 EXPECT_CALL(*mMockHal.get(), on(Eq(12), _))
122 .Times(Exactly(1))
123 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
124 }
125
126 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
127 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
128
129 ASSERT_TRUE(mWrapper->on(10ms, callback).isOk());
130 ASSERT_EQ(1, *callbackCounter.get());
131
132 ASSERT_TRUE(mWrapper->on(11ms, callback).isUnsupported());
133 ASSERT_TRUE(mWrapper->on(12ms, callback).isFailed());
134
135 // Callback not triggered for unsupported and on failure
136 ASSERT_EQ(1, *callbackCounter.get());
137 }
138
TEST_F(VibratorHalWrapperAidlTest,TestOff)139 TEST_F(VibratorHalWrapperAidlTest, TestOff) {
140 EXPECT_CALL(*mMockHal.get(), off())
141 .Times(Exactly(3))
142 .WillOnce(Return(ndk::ScopedAStatus::ok()))
143 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)))
144 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
145
146 ASSERT_TRUE(mWrapper->off().isOk());
147 ASSERT_TRUE(mWrapper->off().isUnsupported());
148 ASSERT_TRUE(mWrapper->off().isFailed());
149 }
150
TEST_F(VibratorHalWrapperAidlTest,TestSetAmplitude)151 TEST_F(VibratorHalWrapperAidlTest, TestSetAmplitude) {
152 {
153 InSequence seq;
154 EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.1f)))
155 .Times(Exactly(1))
156 .WillOnce(Return(ndk::ScopedAStatus::ok()));
157 EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.2f)))
158 .Times(Exactly(1))
159 .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)));
160 EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.5f)))
161 .Times(Exactly(1))
162 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
163 }
164
165 ASSERT_TRUE(mWrapper->setAmplitude(0.1f).isOk());
166 ASSERT_TRUE(mWrapper->setAmplitude(0.2f).isUnsupported());
167 ASSERT_TRUE(mWrapper->setAmplitude(0.5f).isFailed());
168 }
169
TEST_F(VibratorHalWrapperAidlTest,TestSetExternalControl)170 TEST_F(VibratorHalWrapperAidlTest, TestSetExternalControl) {
171 {
172 InSequence seq;
173 EXPECT_CALL(*mMockHal.get(), setExternalControl(Eq(true)))
174 .Times(Exactly(1))
175 .WillOnce(Return(ndk::ScopedAStatus::ok()));
176 EXPECT_CALL(*mMockHal.get(), setExternalControl(Eq(false)))
177 .Times(Exactly(2))
178 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)))
179 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
180 }
181
182 ASSERT_TRUE(mWrapper->setExternalControl(true).isOk());
183 ASSERT_TRUE(mWrapper->setExternalControl(false).isUnsupported());
184 ASSERT_TRUE(mWrapper->setExternalControl(false).isFailed());
185 }
186
TEST_F(VibratorHalWrapperAidlTest,TestAlwaysOnEnable)187 TEST_F(VibratorHalWrapperAidlTest, TestAlwaysOnEnable) {
188 {
189 InSequence seq;
190 EXPECT_CALL(*mMockHal.get(),
191 alwaysOnEnable(Eq(1), Eq(Effect::CLICK), Eq(EffectStrength::LIGHT)))
192 .Times(Exactly(1))
193 .WillOnce(Return(ndk::ScopedAStatus::ok()));
194 EXPECT_CALL(*mMockHal.get(),
195 alwaysOnEnable(Eq(2), Eq(Effect::TICK), Eq(EffectStrength::MEDIUM)))
196 .Times(Exactly(1))
197 .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)));
198 EXPECT_CALL(*mMockHal.get(),
199 alwaysOnEnable(Eq(3), Eq(Effect::POP), Eq(EffectStrength::STRONG)))
200 .Times(Exactly(1))
201 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
202 }
203
204 auto result = mWrapper->alwaysOnEnable(1, Effect::CLICK, EffectStrength::LIGHT);
205 ASSERT_TRUE(result.isOk());
206 result = mWrapper->alwaysOnEnable(2, Effect::TICK, EffectStrength::MEDIUM);
207 ASSERT_TRUE(result.isUnsupported());
208 result = mWrapper->alwaysOnEnable(3, Effect::POP, EffectStrength::STRONG);
209 ASSERT_TRUE(result.isFailed());
210 }
211
TEST_F(VibratorHalWrapperAidlTest,TestAlwaysOnDisable)212 TEST_F(VibratorHalWrapperAidlTest, TestAlwaysOnDisable) {
213 {
214 InSequence seq;
215 EXPECT_CALL(*mMockHal.get(), alwaysOnDisable(Eq(1)))
216 .Times(Exactly(1))
217 .WillOnce(Return(ndk::ScopedAStatus::ok()));
218 EXPECT_CALL(*mMockHal.get(), alwaysOnDisable(Eq(2)))
219 .Times(Exactly(1))
220 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
221 EXPECT_CALL(*mMockHal.get(), alwaysOnDisable(Eq(3)))
222 .Times(Exactly(1))
223 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
224 }
225
226 ASSERT_TRUE(mWrapper->alwaysOnDisable(1).isOk());
227 ASSERT_TRUE(mWrapper->alwaysOnDisable(2).isUnsupported());
228 ASSERT_TRUE(mWrapper->alwaysOnDisable(3).isFailed());
229 }
230
TEST_F(VibratorHalWrapperAidlTest,TestGetInfoDoesNotCacheFailedResult)231 TEST_F(VibratorHalWrapperAidlTest, TestGetInfoDoesNotCacheFailedResult) {
232 constexpr float F_MIN = 100.f;
233 constexpr float F0 = 123.f;
234 constexpr float F_RESOLUTION = 0.5f;
235 constexpr float Q_FACTOR = 123.f;
236 constexpr int32_t COMPOSITION_SIZE_MAX = 10;
237 constexpr int32_t PWLE_SIZE_MAX = 20;
238 constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
239 constexpr int32_t PWLE_DURATION_MAX = 200;
240 constexpr int32_t PWLE_V2_COMPOSITION_SIZE_MAX = 16;
241 constexpr int32_t PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS = 20;
242 constexpr int32_t PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS = 1000;
243 std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
244 std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK};
245 std::vector<Braking> supportedBraking = {Braking::CLAB};
246 std::vector<float> amplitudes = {0.f, 1.f, 0.f};
247 std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap{
248 FrequencyAccelerationMapEntry(/*frequency=*/30.0f,
249 /*maxOutputAcceleration=*/0.2),
250 FrequencyAccelerationMapEntry(/*frequency=*/60.0f,
251 /*maxOutputAcceleration=*/0.8)};
252
253 std::vector<std::chrono::milliseconds> primitiveDurations;
254 constexpr auto primitiveRange = ndk::enum_range<CompositePrimitive>();
255 constexpr auto primitiveCount = std::distance(primitiveRange.begin(), primitiveRange.end());
256 primitiveDurations.resize(primitiveCount);
257 primitiveDurations[static_cast<size_t>(CompositePrimitive::CLICK)] = 10ms;
258
259 EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
260 .Times(Exactly(2))
261 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
262 .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK),
263 Return(ndk::ScopedAStatus::ok())));
264 EXPECT_CALL(*mMockHal.get(), getSupportedEffects(_))
265 .Times(Exactly(2))
266 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
267 .WillOnce(DoAll(SetArgPointee<0>(supportedEffects), Return(ndk::ScopedAStatus::ok())));
268 EXPECT_CALL(*mMockHal.get(), getSupportedBraking(_))
269 .Times(Exactly(2))
270 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
271 .WillOnce(DoAll(SetArgPointee<0>(supportedBraking), Return(ndk::ScopedAStatus::ok())));
272 EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
273 .Times(Exactly(2))
274 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
275 .WillOnce(
276 DoAll(SetArgPointee<0>(supportedPrimitives), Return(ndk::ScopedAStatus::ok())));
277 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _))
278 .Times(Exactly(1))
279 .WillOnce(DoAll(SetArgPointee<1>(10), Return(ndk::ScopedAStatus::ok())));
280 EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
281 .Times(Exactly(2))
282 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
283 .WillOnce(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX),
284 Return(ndk::ScopedAStatus::ok())));
285 EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
286 .Times(Exactly(2))
287 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
288 .WillOnce(
289 DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(ndk::ScopedAStatus::ok())));
290 EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
291 .Times(Exactly(2))
292 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
293 .WillOnce(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(ndk::ScopedAStatus::ok())));
294 EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
295 .Times(Exactly(2))
296 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
297 .WillOnce(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(ndk::ScopedAStatus::ok())));
298 EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
299 .Times(Exactly(2))
300 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
301 .WillOnce(DoAll(SetArgPointee<0>(F_MIN), Return(ndk::ScopedAStatus::ok())));
302 EXPECT_CALL(*mMockHal.get(), getResonantFrequency(_))
303 .Times(Exactly(2))
304 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
305 .WillOnce(DoAll(SetArgPointee<0>(F0), Return(ndk::ScopedAStatus::ok())));
306 EXPECT_CALL(*mMockHal.get(), getFrequencyResolution(_))
307 .Times(Exactly(2))
308 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
309 .WillOnce(DoAll(SetArgPointee<0>(F_RESOLUTION), Return(ndk::ScopedAStatus::ok())));
310 EXPECT_CALL(*mMockHal.get(), getQFactor(_))
311 .Times(Exactly(2))
312 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
313 .WillOnce(DoAll(SetArgPointee<0>(Q_FACTOR), Return(ndk::ScopedAStatus::ok())));
314 EXPECT_CALL(*mMockHal.get(), getBandwidthAmplitudeMap(_))
315 .Times(Exactly(2))
316 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
317 .WillOnce(DoAll(SetArgPointee<0>(amplitudes), Return(ndk::ScopedAStatus::ok())));
318 EXPECT_CALL(*mMockHal.get(), getPwleV2CompositionSizeMax(_))
319 .Times(Exactly(2))
320 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
321 .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_COMPOSITION_SIZE_MAX),
322 Return(ndk::ScopedAStatus::ok())));
323 EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMinMillis(_))
324 .Times(Exactly(2))
325 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
326 .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
327 Return(ndk::ScopedAStatus::ok())));
328 EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMaxMillis(_))
329 .Times(Exactly(2))
330 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
331 .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
332 Return(ndk::ScopedAStatus::ok())));
333 EXPECT_CALL(*mMockHal.get(), getFrequencyToOutputAccelerationMap(_))
334 .Times(Exactly(2))
335 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
336 .WillOnce(DoAll(SetArgPointee<0>(frequencyToOutputAccelerationMap),
337 Return(ndk::ScopedAStatus::ok())));
338
339 vibrator::Info failed = mWrapper->getInfo();
340 ASSERT_TRUE(failed.capabilities.isFailed());
341 ASSERT_TRUE(failed.supportedEffects.isFailed());
342 ASSERT_TRUE(failed.supportedBraking.isFailed());
343 ASSERT_TRUE(failed.supportedPrimitives.isFailed());
344 ASSERT_TRUE(failed.primitiveDurations.isFailed());
345 ASSERT_TRUE(failed.primitiveDelayMax.isFailed());
346 ASSERT_TRUE(failed.pwlePrimitiveDurationMax.isFailed());
347 ASSERT_TRUE(failed.compositionSizeMax.isFailed());
348 ASSERT_TRUE(failed.pwleSizeMax.isFailed());
349 ASSERT_TRUE(failed.minFrequency.isFailed());
350 ASSERT_TRUE(failed.resonantFrequency.isFailed());
351 ASSERT_TRUE(failed.frequencyResolution.isFailed());
352 ASSERT_TRUE(failed.qFactor.isFailed());
353 ASSERT_TRUE(failed.maxAmplitudes.isFailed());
354 ASSERT_TRUE(failed.maxEnvelopeEffectSize.isFailed());
355 ASSERT_TRUE(failed.minEnvelopeEffectControlPointDuration.isFailed());
356 ASSERT_TRUE(failed.maxEnvelopeEffectControlPointDuration.isFailed());
357 ASSERT_TRUE(failed.frequencyToOutputAccelerationMap.isFailed());
358
359 vibrator::Info successful = mWrapper->getInfo();
360 ASSERT_EQ(vibrator::Capabilities::ON_CALLBACK, successful.capabilities.value());
361 ASSERT_EQ(supportedEffects, successful.supportedEffects.value());
362 ASSERT_EQ(supportedBraking, successful.supportedBraking.value());
363 ASSERT_EQ(supportedPrimitives, successful.supportedPrimitives.value());
364 ASSERT_EQ(primitiveDurations, successful.primitiveDurations.value());
365 ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), successful.primitiveDelayMax.value());
366 ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX),
367 successful.pwlePrimitiveDurationMax.value());
368 ASSERT_EQ(COMPOSITION_SIZE_MAX, successful.compositionSizeMax.value());
369 ASSERT_EQ(PWLE_SIZE_MAX, successful.pwleSizeMax.value());
370 ASSERT_EQ(F_MIN, successful.minFrequency.value());
371 ASSERT_EQ(F0, successful.resonantFrequency.value());
372 ASSERT_EQ(F_RESOLUTION, successful.frequencyResolution.value());
373 ASSERT_EQ(Q_FACTOR, successful.qFactor.value());
374 ASSERT_EQ(amplitudes, successful.maxAmplitudes.value());
375 ASSERT_EQ(PWLE_V2_COMPOSITION_SIZE_MAX, successful.maxEnvelopeEffectSize.value());
376 ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
377 successful.minEnvelopeEffectControlPointDuration.value());
378 ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
379 successful.maxEnvelopeEffectControlPointDuration.value());
380 ASSERT_EQ(frequencyToOutputAccelerationMap,
381 successful.frequencyToOutputAccelerationMap.value());
382 }
383
TEST_F(VibratorHalWrapperAidlTest,TestGetInfoCachesResult)384 TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
385 constexpr float F_MIN = 100.f;
386 constexpr float F0 = 123.f;
387 constexpr int32_t COMPOSITION_SIZE_MAX = 10;
388 constexpr int32_t PWLE_SIZE_MAX = 20;
389 constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
390 constexpr int32_t PWLE_DURATION_MAX = 200;
391 constexpr int32_t PWLE_V2_COMPOSITION_SIZE_MAX = 16;
392 constexpr int32_t PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS = 20;
393 constexpr int32_t PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS = 1000;
394 std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
395 std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap{
396 FrequencyAccelerationMapEntry(/*frequency=*/30.0f,
397 /*maxOutputAcceleration=*/0.2),
398 FrequencyAccelerationMapEntry(/*frequency=*/60.0f,
399 /*maxOutputAcceleration=*/0.8)};
400
401 EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
402 .Times(Exactly(1))
403 .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK),
404 Return(ndk::ScopedAStatus::ok())));
405 EXPECT_CALL(*mMockHal.get(), getSupportedEffects(_))
406 .Times(Exactly(1))
407 .WillOnce(DoAll(SetArgPointee<0>(supportedEffects), Return(ndk::ScopedAStatus::ok())));
408 EXPECT_CALL(*mMockHal.get(), getQFactor(_))
409 .Times(Exactly(1))
410 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
411 EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
412 .Times(Exactly(1))
413 .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)));
414 EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
415 .Times(Exactly(1))
416 .WillOnce(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX),
417 Return(ndk::ScopedAStatus::ok())));
418 EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
419 .Times(Exactly(1))
420 .WillOnce(
421 DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(ndk::ScopedAStatus::ok())));
422 EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
423 .Times(Exactly(1))
424 .WillOnce(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(ndk::ScopedAStatus::ok())));
425 EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
426 .Times(Exactly(1))
427 .WillOnce(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(ndk::ScopedAStatus::ok())));
428 EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
429 .Times(Exactly(1))
430 .WillOnce(DoAll(SetArgPointee<0>(F_MIN), Return(ndk::ScopedAStatus::ok())));
431 EXPECT_CALL(*mMockHal.get(), getResonantFrequency(_))
432 .Times(Exactly(1))
433 .WillOnce(DoAll(SetArgPointee<0>(F0), Return(ndk::ScopedAStatus::ok())));
434 EXPECT_CALL(*mMockHal.get(), getFrequencyResolution(_))
435 .Times(Exactly(1))
436 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
437 EXPECT_CALL(*mMockHal.get(), getBandwidthAmplitudeMap(_))
438 .Times(Exactly(1))
439 .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)));
440 EXPECT_CALL(*mMockHal.get(), getSupportedBraking(_))
441 .Times(Exactly(1))
442 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
443 EXPECT_CALL(*mMockHal.get(), getPwleV2CompositionSizeMax(_))
444 .Times(Exactly(1))
445 .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_COMPOSITION_SIZE_MAX),
446 Return(ndk::ScopedAStatus::ok())));
447 EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMinMillis(_))
448 .Times(Exactly(1))
449 .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
450 Return(ndk::ScopedAStatus::ok())));
451 EXPECT_CALL(*mMockHal.get(), getPwleV2PrimitiveDurationMaxMillis(_))
452 .Times(Exactly(1))
453 .WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
454 Return(ndk::ScopedAStatus::ok())));
455 EXPECT_CALL(*mMockHal.get(), getFrequencyToOutputAccelerationMap(_))
456 .Times(Exactly(1))
457 .WillOnce(DoAll(SetArgPointee<0>(frequencyToOutputAccelerationMap),
458 Return(ndk::ScopedAStatus::ok())));
459
460 std::vector<std::thread> threads;
461 for (int i = 0; i < 10; i++) {
462 threads.push_back(
463 std::thread([&]() { ASSERT_TRUE(mWrapper->getInfo().capabilities.isOk()); }));
464 }
465 std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
466
467 vibrator::Info info = mWrapper->getInfo();
468 ASSERT_EQ(vibrator::Capabilities::ON_CALLBACK, info.capabilities.value());
469 ASSERT_EQ(supportedEffects, info.supportedEffects.value());
470 ASSERT_TRUE(info.supportedBraking.isUnsupported());
471 ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
472 ASSERT_TRUE(info.primitiveDurations.isUnsupported());
473 ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), info.primitiveDelayMax.value());
474 ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX), info.pwlePrimitiveDurationMax.value());
475 ASSERT_EQ(COMPOSITION_SIZE_MAX, info.compositionSizeMax.value());
476 ASSERT_EQ(PWLE_SIZE_MAX, info.pwleSizeMax.value());
477 ASSERT_EQ(F_MIN, info.minFrequency.value());
478 ASSERT_EQ(F0, info.resonantFrequency.value());
479 ASSERT_TRUE(info.frequencyResolution.isUnsupported());
480 ASSERT_TRUE(info.qFactor.isUnsupported());
481 ASSERT_TRUE(info.maxAmplitudes.isUnsupported());
482 ASSERT_EQ(PWLE_V2_COMPOSITION_SIZE_MAX, info.maxEnvelopeEffectSize.value());
483 ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS),
484 info.minEnvelopeEffectControlPointDuration.value());
485 ASSERT_EQ(std::chrono::milliseconds(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
486 info.maxEnvelopeEffectControlPointDuration.value());
487 ASSERT_EQ(frequencyToOutputAccelerationMap, info.frequencyToOutputAccelerationMap.value());
488 }
489
TEST_F(VibratorHalWrapperAidlTest,TestPerformEffectWithCallbackSupport)490 TEST_F(VibratorHalWrapperAidlTest, TestPerformEffectWithCallbackSupport) {
491 {
492 InSequence seq;
493 EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
494 .Times(Exactly(1))
495 .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_PERFORM_CALLBACK),
496 Return(ndk::ScopedAStatus::ok())));
497 EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::CLICK), Eq(EffectStrength::LIGHT), _, _))
498 .Times(Exactly(1))
499 .WillOnce(DoAll(SetArgPointee<3>(1000), WithArg<2>(vibrator::TriggerCallback()),
500 Return(ndk::ScopedAStatus::ok())));
501 EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::POP), Eq(EffectStrength::MEDIUM), _, _))
502 .Times(Exactly(1))
503 .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)));
504 EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::THUD), Eq(EffectStrength::STRONG), _, _))
505 .Times(Exactly(1))
506 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
507 }
508
509 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
510 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
511
512 auto result = mWrapper->performEffect(Effect::CLICK, EffectStrength::LIGHT, callback);
513 ASSERT_TRUE(result.isOk());
514 ASSERT_EQ(1000ms, result.value());
515 ASSERT_EQ(1, *callbackCounter.get());
516
517 result = mWrapper->performEffect(Effect::POP, EffectStrength::MEDIUM, callback);
518 ASSERT_TRUE(result.isUnsupported());
519 // Callback not triggered for unsupported
520 ASSERT_EQ(1, *callbackCounter.get());
521
522 result = mWrapper->performEffect(Effect::THUD, EffectStrength::STRONG, callback);
523 ASSERT_TRUE(result.isFailed());
524 // Callback not triggered on failure
525 ASSERT_EQ(1, *callbackCounter.get());
526 }
527
TEST_F(VibratorHalWrapperAidlTest,TestPerformEffectWithoutCallbackSupport)528 TEST_F(VibratorHalWrapperAidlTest, TestPerformEffectWithoutCallbackSupport) {
529 {
530 InSequence seq;
531 EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
532 .Times(Exactly(1))
533 .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK),
534 Return(ndk::ScopedAStatus::ok())));
535 EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::CLICK), Eq(EffectStrength::LIGHT), _, _))
536 .Times(Exactly(1))
537 .WillOnce(DoAll(SetArgPointee<3>(10), Return(ndk::ScopedAStatus::ok())));
538 EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms)))
539 .Times(Exactly(1))
540 .WillOnce(vibrator::TriggerSchedulerCallback());
541 EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::POP), Eq(EffectStrength::MEDIUM), _, _))
542 .Times(Exactly(1))
543 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
544 EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::THUD), Eq(EffectStrength::STRONG), _, _))
545 .Times(Exactly(1))
546 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
547 }
548
549 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
550 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
551
552 auto result = mWrapper->performEffect(Effect::CLICK, EffectStrength::LIGHT, callback);
553 ASSERT_TRUE(result.isOk());
554 ASSERT_EQ(10ms, result.value());
555 ASSERT_EQ(1, *callbackCounter.get());
556
557 result = mWrapper->performEffect(Effect::POP, EffectStrength::MEDIUM, callback);
558 ASSERT_TRUE(result.isUnsupported());
559
560 result = mWrapper->performEffect(Effect::THUD, EffectStrength::STRONG, callback);
561 ASSERT_TRUE(result.isFailed());
562
563 // Callback not triggered for unsupported and on failure
564 ASSERT_EQ(1, *callbackCounter.get());
565 }
566
TEST_F(VibratorHalWrapperAidlTest,TestPerformVendorEffect)567 TEST_F(VibratorHalWrapperAidlTest, TestPerformVendorEffect) {
568 PersistableBundle vendorData;
569 vendorData.putInt("key", 1);
570 VendorEffect vendorEffect;
571 vendorEffect.vendorData = vendorData;
572 vendorEffect.strength = EffectStrength::MEDIUM;
573 vendorEffect.scale = 0.5f;
574
575 {
576 InSequence seq;
577 EXPECT_CALL(*mMockHal.get(), performVendorEffect(_, _))
578 .Times(Exactly(3))
579 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)))
580 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
581 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
582 Return(ndk::ScopedAStatus::ok())));
583 }
584
585 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
586 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
587
588 auto result = mWrapper->performVendorEffect(vendorEffect, callback);
589 ASSERT_TRUE(result.isUnsupported());
590 // Callback not triggered on failure
591 ASSERT_EQ(0, *callbackCounter.get());
592
593 result = mWrapper->performVendorEffect(vendorEffect, callback);
594 ASSERT_TRUE(result.isFailed());
595 // Callback not triggered for unsupported
596 ASSERT_EQ(0, *callbackCounter.get());
597
598 result = mWrapper->performVendorEffect(vendorEffect, callback);
599 ASSERT_TRUE(result.isOk());
600 ASSERT_EQ(1, *callbackCounter.get());
601 }
602
TEST_F(VibratorHalWrapperAidlTest,TestPerformComposedEffect)603 TEST_F(VibratorHalWrapperAidlTest, TestPerformComposedEffect) {
604 std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK,
605 CompositePrimitive::SPIN,
606 CompositePrimitive::THUD};
607 std::vector<CompositeEffect> emptyEffects, singleEffect, multipleEffects;
608 singleEffect.push_back(
609 vibrator::TestFactory::createCompositeEffect(CompositePrimitive::CLICK, 10ms, 0.0f));
610 multipleEffects.push_back(
611 vibrator::TestFactory::createCompositeEffect(CompositePrimitive::SPIN, 100ms, 0.5f));
612 multipleEffects.push_back(
613 vibrator::TestFactory::createCompositeEffect(CompositePrimitive::THUD, 1000ms, 1.0f));
614
615 {
616 InSequence seq;
617 EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
618 .Times(Exactly(1))
619 .WillOnce(DoAll(SetArgPointee<0>(supportedPrimitives),
620 Return(ndk::ScopedAStatus::ok())));
621 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _))
622 .Times(Exactly(1))
623 .WillOnce(DoAll(SetArgPointee<1>(1), Return(ndk::ScopedAStatus::ok())));
624 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::SPIN), _))
625 .Times(Exactly(1))
626 .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok())));
627 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::THUD), _))
628 .Times(Exactly(1))
629 .WillOnce(DoAll(SetArgPointee<1>(3), Return(ndk::ScopedAStatus::ok())));
630
631 EXPECT_CALL(*mMockHal.get(), compose(Eq(emptyEffects), _))
632 .Times(Exactly(1))
633 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
634 Return(ndk::ScopedAStatus::ok())));
635 EXPECT_CALL(*mMockHal.get(), compose(Eq(singleEffect), _))
636 .Times(Exactly(1))
637 .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)));
638 EXPECT_CALL(*mMockHal.get(), compose(Eq(multipleEffects), _))
639 .Times(Exactly(1))
640 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
641 }
642
643 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
644 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
645
646 auto result = mWrapper->performComposedEffect(emptyEffects, callback);
647 ASSERT_TRUE(result.isOk());
648 ASSERT_EQ(0ms, result.value());
649 ASSERT_EQ(1, *callbackCounter.get());
650
651 result = mWrapper->performComposedEffect(singleEffect, callback);
652 ASSERT_TRUE(result.isUnsupported());
653 // Callback not triggered for unsupported
654 ASSERT_EQ(1, *callbackCounter.get());
655
656 result = mWrapper->performComposedEffect(multipleEffects, callback);
657 ASSERT_TRUE(result.isFailed());
658 // Callback not triggered on failure
659 ASSERT_EQ(1, *callbackCounter.get());
660 }
661
TEST_F(VibratorHalWrapperAidlTest,TestPerformComposedCachesPrimitiveDurationsAndIgnoresFailures)662 TEST_F(VibratorHalWrapperAidlTest, TestPerformComposedCachesPrimitiveDurationsAndIgnoresFailures) {
663 std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::SPIN,
664 CompositePrimitive::THUD};
665 std::vector<CompositeEffect> multipleEffects;
666 multipleEffects.push_back(
667 vibrator::TestFactory::createCompositeEffect(CompositePrimitive::SPIN, 10ms, 0.5f));
668 multipleEffects.push_back(
669 vibrator::TestFactory::createCompositeEffect(CompositePrimitive::THUD, 100ms, 1.0f));
670
671 {
672 InSequence seq;
673 EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
674 .Times(Exactly(1))
675 .WillOnce(DoAll(SetArgPointee<0>(supportedPrimitives),
676 Return(ndk::ScopedAStatus::ok())));
677 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::SPIN), _))
678 .Times(Exactly(1))
679 .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok())));
680 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::THUD), _))
681 .Times(Exactly(1))
682 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)));
683 EXPECT_CALL(*mMockHal.get(), compose(Eq(multipleEffects), _))
684 .Times(Exactly(1))
685 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
686 Return(ndk::ScopedAStatus::ok())));
687
688 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::SPIN), _))
689 .Times(Exactly(1))
690 .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok())));
691 EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::THUD), _))
692 .Times(Exactly(1))
693 .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok())));
694 EXPECT_CALL(*mMockHal.get(), compose(Eq(multipleEffects), _))
695 .Times(Exactly(2))
696 // ndk::ScopedAStatus::ok() cannot be copy-constructed so can't use WillRepeatedly
697 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
698 Return(ndk::ScopedAStatus::ok())))
699 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
700 Return(ndk::ScopedAStatus::ok())));
701 }
702
703 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
704 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
705
706 auto result = mWrapper->performComposedEffect(multipleEffects, callback);
707 ASSERT_TRUE(result.isOk());
708 ASSERT_EQ(112ms, result.value()); // Failed primitive durations counted as 1.
709 ASSERT_EQ(1, *callbackCounter.get());
710
711 result = mWrapper->performComposedEffect(multipleEffects, callback);
712 ASSERT_TRUE(result.isOk());
713 ASSERT_EQ(114ms, result.value()); // Second fetch succeeds and returns primitive duration.
714 ASSERT_EQ(2, *callbackCounter.get());
715
716 result = mWrapper->performComposedEffect(multipleEffects, callback);
717 ASSERT_TRUE(result.isOk());
718 ASSERT_EQ(114ms, result.value()); // Cached durations not fetched again, same duration returned.
719 ASSERT_EQ(3, *callbackCounter.get());
720 }
721
TEST_F(VibratorHalWrapperAidlTest,TestPerformPwleEffect)722 TEST_F(VibratorHalWrapperAidlTest, TestPerformPwleEffect) {
723 std::vector<PrimitivePwle> emptyPrimitives, multiplePrimitives;
724 multiplePrimitives.push_back(vibrator::TestFactory::createActivePwle(0, 1, 0, 1, 10ms));
725 multiplePrimitives.push_back(vibrator::TestFactory::createBrakingPwle(Braking::NONE, 100ms));
726
727 {
728 InSequence seq;
729 EXPECT_CALL(*mMockHal.get(), composePwle(Eq(emptyPrimitives), _))
730 .Times(Exactly(1))
731 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)));
732 EXPECT_CALL(*mMockHal.get(), composePwle(Eq(multiplePrimitives), _))
733 .Times(Exactly(2))
734 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
735 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
736 Return(ndk::ScopedAStatus::ok())));
737 }
738
739 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
740 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
741
742 auto result = mWrapper->performPwleEffect(emptyPrimitives, callback);
743 ASSERT_TRUE(result.isUnsupported());
744 // Callback not triggered on failure
745 ASSERT_EQ(0, *callbackCounter.get());
746
747 result = mWrapper->performPwleEffect(multiplePrimitives, callback);
748 ASSERT_TRUE(result.isFailed());
749 // Callback not triggered for unsupported
750 ASSERT_EQ(0, *callbackCounter.get());
751
752 result = mWrapper->performPwleEffect(multiplePrimitives, callback);
753 ASSERT_TRUE(result.isOk());
754 ASSERT_EQ(1, *callbackCounter.get());
755 }
756
TEST_F(VibratorHalWrapperAidlTest,TestComposePwleV2)757 TEST_F(VibratorHalWrapperAidlTest, TestComposePwleV2) {
758 CompositePwleV2 composite;
759 composite.pwlePrimitives = {
760 PwleV2Primitive(/*amplitude=*/0.2, /*frequency=*/50, /*time=*/100),
761 PwleV2Primitive(/*amplitude=*/0.5, /*frequency=*/150, /*time=*/100),
762 PwleV2Primitive(/*amplitude=*/0.8, /*frequency=*/250, /*time=*/100),
763 };
764
765 {
766 InSequence seq;
767 EXPECT_CALL(*mMockHal.get(), composePwleV2(_, _))
768 .Times(Exactly(3))
769 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)))
770 .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
771 .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
772 Return(ndk::ScopedAStatus::ok())));
773 }
774
775 std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
776 auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
777
778 auto result = mWrapper->composePwleV2(composite, callback);
779 ASSERT_TRUE(result.isUnsupported());
780 // Callback not triggered on failure
781 ASSERT_EQ(0, *callbackCounter.get());
782
783 result = mWrapper->composePwleV2(composite, callback);
784 ASSERT_TRUE(result.isFailed());
785 // Callback not triggered for unsupported
786 ASSERT_EQ(0, *callbackCounter.get());
787
788 result = mWrapper->composePwleV2(composite, callback);
789 ASSERT_TRUE(result.isOk());
790 ASSERT_EQ(1, *callbackCounter.get());
791 }
792