xref: /aosp_15_r20/frameworks/native/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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