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 "VibratorManagerHalControllerTest"
18
19 #include <cutils/atomic.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <utils/Log.h>
24
25 #include <vibratorservice/VibratorManagerHalController.h>
26
27 #include "test_mocks.h"
28 #include "test_utils.h"
29
30 using aidl::android::hardware::vibrator::IVibrationSession;
31 using aidl::android::hardware::vibrator::VibrationSessionConfig;
32 using android::vibrator::HalController;
33
34 using namespace android;
35 using namespace testing;
36
37 static constexpr int MAX_ATTEMPTS = 2;
38 static const std::vector<int32_t> VIBRATOR_IDS = {1, 2};
39 static const VibrationSessionConfig SESSION_CONFIG;
40 static constexpr int VIBRATOR_ID = 1;
41
42 // -------------------------------------------------------------------------------------------------
43
44 class MockManagerHalWrapper : public vibrator::ManagerHalWrapper {
45 public:
46 MOCK_METHOD(void, tryReconnect, (), (override));
47 MOCK_METHOD(vibrator::HalResult<void>, ping, (), (override));
48 MOCK_METHOD(vibrator::HalResult<vibrator::ManagerCapabilities>, getCapabilities, (),
49 (override));
50 MOCK_METHOD(vibrator::HalResult<std::vector<int32_t>>, getVibratorIds, (), (override));
51 MOCK_METHOD(vibrator::HalResult<std::shared_ptr<HalController>>, getVibrator, (int32_t id),
52 (override));
53 MOCK_METHOD(vibrator::HalResult<void>, prepareSynced, (const std::vector<int32_t>& ids),
54 (override));
55 MOCK_METHOD(vibrator::HalResult<void>, triggerSynced,
56 (const std::function<void()>& completionCallback), (override));
57 MOCK_METHOD(vibrator::HalResult<void>, cancelSynced, (), (override));
58 MOCK_METHOD(vibrator::HalResult<std::shared_ptr<IVibrationSession>>, startSession,
59 (const std::vector<int32_t>& ids, const VibrationSessionConfig& s,
60 const std::function<void()>& completionCallback),
61 (override));
62 MOCK_METHOD(vibrator::HalResult<void>, clearSessions, (), (override));
63 };
64
65 // -------------------------------------------------------------------------------------------------
66
67 class VibratorManagerHalControllerTest : public Test {
68 public:
SetUp()69 void SetUp() override {
70 mConnectCounter = 0;
71 auto callbackScheduler = std::make_shared<vibrator::CallbackScheduler>();
72 mMockHal = std::make_shared<StrictMock<MockManagerHalWrapper>>();
73 auto connector = [this](std::shared_ptr<vibrator::CallbackScheduler>) {
74 android_atomic_inc(&mConnectCounter);
75 return mMockHal;
76 };
77 mController = std::make_unique<vibrator::ManagerHalController>(std::move(callbackScheduler),
78 connector);
79 ASSERT_NE(mController, nullptr);
80 }
81
82 protected:
83 int32_t mConnectCounter;
84 std::shared_ptr<MockManagerHalWrapper> mMockHal;
85 std::unique_ptr<vibrator::ManagerHalController> mController;
86
setHalExpectations(int32_t cardinality,vibrator::HalResult<void> voidResult,vibrator::HalResult<vibrator::ManagerCapabilities> capabilitiesResult,vibrator::HalResult<std::vector<int32_t>> idsResult,vibrator::HalResult<std::shared_ptr<HalController>> vibratorResult,vibrator::HalResult<std::shared_ptr<IVibrationSession>> sessionResult)87 void setHalExpectations(int32_t cardinality, vibrator::HalResult<void> voidResult,
88 vibrator::HalResult<vibrator::ManagerCapabilities> capabilitiesResult,
89 vibrator::HalResult<std::vector<int32_t>> idsResult,
90 vibrator::HalResult<std::shared_ptr<HalController>> vibratorResult,
91 vibrator::HalResult<std::shared_ptr<IVibrationSession>> sessionResult) {
92 EXPECT_CALL(*mMockHal.get(), ping())
93 .Times(Exactly(cardinality))
94 .WillRepeatedly(Return(voidResult));
95 EXPECT_CALL(*mMockHal.get(), getCapabilities())
96 .Times(Exactly(cardinality))
97 .WillRepeatedly(Return(capabilitiesResult));
98 EXPECT_CALL(*mMockHal.get(), getVibratorIds())
99 .Times(Exactly(cardinality))
100 .WillRepeatedly(Return(idsResult));
101 EXPECT_CALL(*mMockHal.get(), getVibrator(_))
102 .Times(Exactly(cardinality))
103 .WillRepeatedly(Return(vibratorResult));
104 EXPECT_CALL(*mMockHal.get(), prepareSynced(_))
105 .Times(Exactly(cardinality))
106 .WillRepeatedly(Return(voidResult));
107 EXPECT_CALL(*mMockHal.get(), triggerSynced(_))
108 .Times(Exactly(cardinality))
109 .WillRepeatedly(Return(voidResult));
110 EXPECT_CALL(*mMockHal.get(), cancelSynced())
111 .Times(Exactly(cardinality))
112 .WillRepeatedly(Return(voidResult));
113 EXPECT_CALL(*mMockHal.get(), startSession(_, _, _))
114 .Times(Exactly(cardinality))
115 .WillRepeatedly(Return(sessionResult));
116 EXPECT_CALL(*mMockHal.get(), clearSessions())
117 .Times(Exactly(cardinality))
118 .WillRepeatedly(Return(voidResult));
119
120 if (cardinality > 1) {
121 // One reconnection for each retry.
122 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(9 * (cardinality - 1)));
123 } else {
124 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
125 }
126 }
127 };
128
129 // -------------------------------------------------------------------------------------------------
130
TEST_F(VibratorManagerHalControllerTest,TestInit)131 TEST_F(VibratorManagerHalControllerTest, TestInit) {
132 mController->init();
133 ASSERT_EQ(1, mConnectCounter);
134
135 // Noop when wrapper was already initialized.
136 mController->init();
137 ASSERT_EQ(1, mConnectCounter);
138 }
139
TEST_F(VibratorManagerHalControllerTest,TestApiCallsAreForwardedToHal)140 TEST_F(VibratorManagerHalControllerTest, TestApiCallsAreForwardedToHal) {
141 setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::ok(),
142 vibrator::HalResult<vibrator::ManagerCapabilities>::ok(
143 vibrator::ManagerCapabilities::SYNC),
144 vibrator::HalResult<std::vector<int32_t>>::ok(VIBRATOR_IDS),
145 vibrator::HalResult<std::shared_ptr<HalController>>::ok(nullptr),
146 vibrator::HalResult<std::shared_ptr<IVibrationSession>>::ok(nullptr));
147
148 ASSERT_TRUE(mController->ping().isOk());
149
150 auto getCapabilitiesResult = mController->getCapabilities();
151 ASSERT_TRUE(getCapabilitiesResult.isOk());
152 ASSERT_EQ(vibrator::ManagerCapabilities::SYNC, getCapabilitiesResult.value());
153
154 auto getVibratorIdsResult = mController->getVibratorIds();
155 ASSERT_TRUE(getVibratorIdsResult.isOk());
156 ASSERT_EQ(VIBRATOR_IDS, getVibratorIdsResult.value());
157
158 auto getVibratorResult = mController->getVibrator(VIBRATOR_ID);
159 ASSERT_TRUE(getVibratorResult.isOk());
160 ASSERT_EQ(nullptr, getVibratorResult.value());
161
162 ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isOk());
163 ASSERT_TRUE(mController->triggerSynced([]() {}).isOk());
164 ASSERT_TRUE(mController->cancelSynced().isOk());
165 ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isOk());
166 ASSERT_TRUE(mController->clearSessions().isOk());
167
168 ASSERT_EQ(1, mConnectCounter);
169 }
170
TEST_F(VibratorManagerHalControllerTest,TestUnsupportedApiResultDoesNotResetHalConnection)171 TEST_F(VibratorManagerHalControllerTest, TestUnsupportedApiResultDoesNotResetHalConnection) {
172 setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::unsupported(),
173 vibrator::HalResult<vibrator::ManagerCapabilities>::unsupported(),
174 vibrator::HalResult<std::vector<int32_t>>::unsupported(),
175 vibrator::HalResult<std::shared_ptr<HalController>>::unsupported(),
176 vibrator::HalResult<std::shared_ptr<IVibrationSession>>::unsupported());
177
178 ASSERT_TRUE(mController->ping().isUnsupported());
179 ASSERT_TRUE(mController->getCapabilities().isUnsupported());
180 ASSERT_TRUE(mController->getVibratorIds().isUnsupported());
181 ASSERT_TRUE(mController->getVibrator(VIBRATOR_ID).isUnsupported());
182 ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isUnsupported());
183 ASSERT_TRUE(mController->triggerSynced([]() {}).isUnsupported());
184 ASSERT_TRUE(mController->cancelSynced().isUnsupported());
185 ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isUnsupported());
186 ASSERT_TRUE(mController->clearSessions().isUnsupported());
187
188 ASSERT_EQ(1, mConnectCounter);
189 }
190
TEST_F(VibratorManagerHalControllerTest,TestOperationFailedApiResultDoesNotResetHalConnection)191 TEST_F(VibratorManagerHalControllerTest, TestOperationFailedApiResultDoesNotResetHalConnection) {
192 setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::failed("msg"),
193 vibrator::HalResult<vibrator::ManagerCapabilities>::failed("msg"),
194 vibrator::HalResult<std::vector<int32_t>>::failed("msg"),
195 vibrator::HalResult<std::shared_ptr<HalController>>::failed("msg"),
196 vibrator::HalResult<std::shared_ptr<IVibrationSession>>::failed("msg"));
197
198 ASSERT_TRUE(mController->ping().isFailed());
199 ASSERT_TRUE(mController->getCapabilities().isFailed());
200 ASSERT_TRUE(mController->getVibratorIds().isFailed());
201 ASSERT_TRUE(mController->getVibrator(VIBRATOR_ID).isFailed());
202 ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isFailed());
203 ASSERT_TRUE(mController->triggerSynced([]() {}).isFailed());
204 ASSERT_TRUE(mController->cancelSynced().isFailed());
205 ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isFailed());
206 ASSERT_TRUE(mController->clearSessions().isFailed());
207
208 ASSERT_EQ(1, mConnectCounter);
209 }
210
TEST_F(VibratorManagerHalControllerTest,TestTransactionFailedApiResultResetsHalConnection)211 TEST_F(VibratorManagerHalControllerTest, TestTransactionFailedApiResultResetsHalConnection) {
212 setHalExpectations(MAX_ATTEMPTS, vibrator::HalResult<void>::transactionFailed("m"),
213 vibrator::HalResult<vibrator::ManagerCapabilities>::transactionFailed("m"),
214 vibrator::HalResult<std::vector<int32_t>>::transactionFailed("m"),
215 vibrator::HalResult<std::shared_ptr<HalController>>::transactionFailed("m"),
216 vibrator::HalResult<std::shared_ptr<IVibrationSession>>::transactionFailed(
217 "m"));
218
219 ASSERT_TRUE(mController->ping().isFailed());
220 ASSERT_TRUE(mController->getCapabilities().isFailed());
221 ASSERT_TRUE(mController->getVibratorIds().isFailed());
222 ASSERT_TRUE(mController->getVibrator(VIBRATOR_ID).isFailed());
223 ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isFailed());
224 ASSERT_TRUE(mController->triggerSynced([]() {}).isFailed());
225 ASSERT_TRUE(mController->cancelSynced().isFailed());
226 ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isFailed());
227 ASSERT_TRUE(mController->clearSessions().isFailed());
228
229 ASSERT_EQ(1, mConnectCounter);
230 }
231
TEST_F(VibratorManagerHalControllerTest,TestFailedApiResultReturnsSuccessAfterRetries)232 TEST_F(VibratorManagerHalControllerTest, TestFailedApiResultReturnsSuccessAfterRetries) {
233 {
234 InSequence seq;
235 EXPECT_CALL(*mMockHal.get(), ping())
236 .Times(Exactly(1))
237 .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
238 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
239 EXPECT_CALL(*mMockHal.get(), ping())
240 .Times(Exactly(1))
241 .WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
242 }
243
244 ASSERT_TRUE(mController->ping().isOk());
245 ASSERT_EQ(1, mConnectCounter);
246 }
247
TEST_F(VibratorManagerHalControllerTest,TestMultiThreadConnectsOnlyOnce)248 TEST_F(VibratorManagerHalControllerTest, TestMultiThreadConnectsOnlyOnce) {
249 ASSERT_EQ(0, mConnectCounter);
250
251 EXPECT_CALL(*mMockHal.get(), ping())
252 .Times(Exactly(10))
253 .WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
254
255 std::vector<std::thread> threads;
256 for (int i = 0; i < 10; i++) {
257 threads.push_back(std::thread([&]() { ASSERT_TRUE(mController->ping().isOk()); }));
258 }
259 std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
260
261 // Connector was called only by the first thread to use the api.
262 ASSERT_EQ(1, mConnectCounter);
263 }
264