1 /*
2 * Copyright (C) 2025 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 "VibratorControllerTest"
18
19 #include <aidl/android/hardware/vibrator/IVibrator.h>
20
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23
24 #include <utils/Log.h>
25 #include <thread>
26
27 #include <vibratorservice/VibratorController.h>
28
29 #include "test_mocks.h"
30 #include "test_utils.h"
31
32 using ::aidl::android::hardware::vibrator::Effect;
33 using ::aidl::android::hardware::vibrator::EffectStrength;
34 using ::aidl::android::hardware::vibrator::IVibrator;
35
36 using namespace android;
37 using namespace testing;
38
__anonc94ddda40102() 39 const auto kReturnOk = []() { return ndk::ScopedAStatus::ok(); };
__anonc94ddda40202() 40 const auto kReturnUnsupported = []() {
41 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
42 };
__anonc94ddda40302() 43 const auto kReturnTransactionFailed = []() {
44 return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
45 };
__anonc94ddda40402() 46 const auto kReturnUnknownTransaction = []() {
47 return ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION);
48 };
__anonc94ddda40502() 49 const auto kReturnIllegalArgument = []() {
50 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
51 };
52
53 // -------------------------------------------------------------------------------------------------
54
55 /* Provides mock IVibrator instance for testing. */
56 class FakeVibratorProvider : public vibrator::VibratorProvider {
57 public:
FakeVibratorProvider()58 FakeVibratorProvider()
59 : mIsDeclared(true),
60 mMockVibrator(ndk::SharedRefBase::make<StrictMock<vibrator::MockIVibrator>>()),
61 mConnectCount(0),
62 mReconnectCount(0) {}
63 virtual ~FakeVibratorProvider() = default;
64
isDeclared()65 bool isDeclared() override { return mIsDeclared; }
66
waitForVibrator()67 std::shared_ptr<IVibrator> waitForVibrator() override {
68 mConnectCount++;
69 return mIsDeclared ? mMockVibrator : nullptr;
70 }
71
checkForVibrator()72 std::shared_ptr<IVibrator> checkForVibrator() override {
73 mReconnectCount++;
74 return mIsDeclared ? mMockVibrator : nullptr;
75 }
76
setDeclared(bool isDeclared)77 void setDeclared(bool isDeclared) { mIsDeclared = isDeclared; }
78
getConnectCount()79 int32_t getConnectCount() { return mConnectCount; }
80
getReconnectCount()81 int32_t getReconnectCount() { return mReconnectCount; }
82
getMockVibrator()83 std::shared_ptr<StrictMock<vibrator::MockIVibrator>> getMockVibrator() { return mMockVibrator; }
84
85 private:
86 bool mIsDeclared;
87 std::shared_ptr<StrictMock<vibrator::MockIVibrator>> mMockVibrator;
88 int32_t mConnectCount;
89 int32_t mReconnectCount;
90 };
91
92 // -------------------------------------------------------------------------------------------------
93
94 class VibratorControllerTest : public Test {
95 public:
SetUp()96 void SetUp() override {
97 mProvider = std::make_shared<FakeVibratorProvider>();
98 mController = std::make_unique<vibrator::VibratorController>(mProvider);
99 ASSERT_NE(mController, nullptr);
100 }
101
102 protected:
103 std::shared_ptr<FakeVibratorProvider> mProvider = nullptr;
104 std::unique_ptr<vibrator::VibratorController> mController = nullptr;
105 };
106
107 // -------------------------------------------------------------------------------------------------
108
TEST_F(VibratorControllerTest,TestInitServiceDeclared)109 TEST_F(VibratorControllerTest, TestInitServiceDeclared) {
110 ASSERT_TRUE(mController->init());
111 ASSERT_EQ(1, mProvider->getConnectCount());
112 ASSERT_EQ(0, mProvider->getReconnectCount());
113
114 // Noop when wrapper was already initialized.
115 ASSERT_TRUE(mController->init());
116 ASSERT_EQ(1, mProvider->getConnectCount());
117 ASSERT_EQ(0, mProvider->getReconnectCount());
118 }
119
TEST_F(VibratorControllerTest,TestInitServiceNotDeclared)120 TEST_F(VibratorControllerTest, TestInitServiceNotDeclared) {
121 mProvider->setDeclared(false);
122
123 ASSERT_FALSE(mController->init());
124 ASSERT_EQ(0, mProvider->getConnectCount());
125 ASSERT_EQ(0, mProvider->getReconnectCount());
126
127 ASSERT_FALSE(mController->init());
128 ASSERT_EQ(0, mProvider->getConnectCount());
129 ASSERT_EQ(0, mProvider->getReconnectCount());
130 }
131
TEST_F(VibratorControllerTest,TestFirstCallTriggersInit)132 TEST_F(VibratorControllerTest, TestFirstCallTriggersInit) {
133 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
134 .Times(Exactly(1))
135 .WillRepeatedly(kReturnOk);
136
137 auto status = mController->off();
138 ASSERT_TRUE(status.isOk());
139 ASSERT_EQ(1, mProvider->getConnectCount());
140 }
141
TEST_F(VibratorControllerTest,TestSuccessfulResultDoesNotRetry)142 TEST_F(VibratorControllerTest, TestSuccessfulResultDoesNotRetry) {
143 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
144 .Times(Exactly(1))
145 .WillRepeatedly(kReturnOk);
146
147 auto status = mController->off();
148 ASSERT_TRUE(status.isOk());
149 ASSERT_EQ(0, mProvider->getReconnectCount());
150 }
151
TEST_F(VibratorControllerTest,TestUnsupportedOperationResultDoesNotRetry)152 TEST_F(VibratorControllerTest, TestUnsupportedOperationResultDoesNotRetry) {
153 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
154 .Times(Exactly(1))
155 .WillRepeatedly(kReturnUnsupported);
156
157 auto status = mController->off();
158 ASSERT_FALSE(status.isOk());
159 ASSERT_EQ(0, mProvider->getReconnectCount());
160 }
161
TEST_F(VibratorControllerTest,TestUnknownTransactionResultDoesNotRetry)162 TEST_F(VibratorControllerTest, TestUnknownTransactionResultDoesNotRetry) {
163 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
164 .Times(Exactly(1))
165 .WillRepeatedly(kReturnUnknownTransaction);
166
167 auto status = mController->off();
168 ASSERT_FALSE(status.isOk());
169 ASSERT_EQ(0, mProvider->getReconnectCount());
170 }
171
TEST_F(VibratorControllerTest,TestOperationFailedDoesNotRetry)172 TEST_F(VibratorControllerTest, TestOperationFailedDoesNotRetry) {
173 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
174 .Times(Exactly(1))
175 .WillRepeatedly(kReturnIllegalArgument);
176
177 auto status = mController->off();
178 ASSERT_FALSE(status.isOk());
179 ASSERT_EQ(0, mProvider->getReconnectCount());
180 }
181
TEST_F(VibratorControllerTest,TestTransactionFailedRetriesOnlyOnce)182 TEST_F(VibratorControllerTest, TestTransactionFailedRetriesOnlyOnce) {
183 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
184 .Times(Exactly(2))
185 .WillRepeatedly(kReturnTransactionFailed);
186
187 auto status = mController->off();
188 ASSERT_FALSE(status.isOk());
189 ASSERT_EQ(1, mProvider->getReconnectCount());
190 }
191
TEST_F(VibratorControllerTest,TestTransactionFailedThenSucceedsReturnsSuccessAfterRetries)192 TEST_F(VibratorControllerTest, TestTransactionFailedThenSucceedsReturnsSuccessAfterRetries) {
193 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
194 .Times(Exactly(2))
195 .WillOnce(kReturnTransactionFailed)
196 .WillRepeatedly(kReturnOk);
197
198 auto status = mController->off();
199 ASSERT_TRUE(status.isOk());
200 ASSERT_EQ(1, mProvider->getReconnectCount());
201 }
202
TEST_F(VibratorControllerTest,TestOff)203 TEST_F(VibratorControllerTest, TestOff) {
204 EXPECT_CALL(*mProvider->getMockVibrator().get(), off())
205 .Times(Exactly(1))
206 .WillRepeatedly(kReturnOk);
207
208 auto status = mController->off();
209 ASSERT_TRUE(status.isOk());
210 }
211
TEST_F(VibratorControllerTest,TestSetAmplitude)212 TEST_F(VibratorControllerTest, TestSetAmplitude) {
213 EXPECT_CALL(*mProvider->getMockVibrator().get(), setAmplitude(Eq(0.1f)))
214 .Times(Exactly(1))
215 .WillRepeatedly(kReturnOk);
216 EXPECT_CALL(*mProvider->getMockVibrator().get(), setAmplitude(Eq(0.2f)))
217 .Times(Exactly(1))
218 .WillRepeatedly(kReturnIllegalArgument);
219
220 ASSERT_TRUE(mController->setAmplitude(0.1f).isOk());
221 ASSERT_FALSE(mController->setAmplitude(0.2f).isOk());
222 }
223
TEST_F(VibratorControllerTest,TestSetExternalControl)224 TEST_F(VibratorControllerTest, TestSetExternalControl) {
225 EXPECT_CALL(*mProvider->getMockVibrator().get(), setExternalControl(Eq(false)))
226 .Times(Exactly(1))
227 .WillRepeatedly(kReturnOk);
228 EXPECT_CALL(*mProvider->getMockVibrator().get(), setExternalControl(Eq(true)))
229 .Times(Exactly(1))
230 .WillRepeatedly(kReturnIllegalArgument);
231
232 ASSERT_TRUE(mController->setExternalControl(false).isOk());
233 ASSERT_FALSE(mController->setExternalControl(true).isOk());
234 }
235
TEST_F(VibratorControllerTest,TestAlwaysOnEnable)236 TEST_F(VibratorControllerTest, TestAlwaysOnEnable) {
237 EXPECT_CALL(*mProvider->getMockVibrator().get(),
238 alwaysOnEnable(Eq(1), Eq(Effect::CLICK), Eq(EffectStrength::LIGHT)))
239 .Times(Exactly(1))
240 .WillRepeatedly(kReturnOk);
241 EXPECT_CALL(*mProvider->getMockVibrator().get(),
242 alwaysOnEnable(Eq(2), Eq(Effect::TICK), Eq(EffectStrength::MEDIUM)))
243 .Times(Exactly(1))
244 .WillRepeatedly(kReturnIllegalArgument);
245
246 ASSERT_TRUE(mController->alwaysOnEnable(1, Effect::CLICK, EffectStrength::LIGHT).isOk());
247 ASSERT_FALSE(mController->alwaysOnEnable(2, Effect::TICK, EffectStrength::MEDIUM).isOk());
248 }
249