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 "VibratorHalControllerTest"
18
19 #include <aidl/android/hardware/vibrator/IVibrator.h>
20 #include <cutils/atomic.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/VibratorHalController.h>
30 #include <vibratorservice/VibratorHalWrapper.h>
31
32 #include "test_mocks.h"
33 #include "test_utils.h"
34
35 using aidl::android::hardware::vibrator::Effect;
36 using aidl::android::hardware::vibrator::EffectStrength;
37
38 using std::chrono::milliseconds;
39
40 using namespace android;
41 using namespace std::chrono_literals;
42 using namespace testing;
43
__anon519d1f390102(vibrator::HalWrapper* hal) 44 static const auto ON_FN = [](vibrator::HalWrapper* hal) { return hal->on(10ms, []() {}); };
__anon519d1f390302(vibrator::HalWrapper* hal) 45 static const auto OFF_FN = [](vibrator::HalWrapper* hal) { return hal->off(); };
__anon519d1f390402(vibrator::HalWrapper* hal) 46 static const auto PING_FN = [](vibrator::HalWrapper* hal) { return hal->ping(); };
47
48 // -------------------------------------------------------------------------------------------------
49
50 class VibratorHalControllerTest : public Test {
51 public:
SetUp()52 void SetUp() override {
53 mConnectCounter = 0;
54 auto callbackScheduler = std::make_shared<vibrator::CallbackScheduler>();
55 mMockHal = std::make_shared<StrictMock<vibrator::MockHalWrapper>>(callbackScheduler);
56 mController = std::make_unique<
57 vibrator::HalController>(std::move(callbackScheduler),
58 [&](std::shared_ptr<vibrator::CallbackScheduler>) {
59 android_atomic_inc(&(this->mConnectCounter));
60 return this->mMockHal;
61 });
62 ASSERT_NE(mController, nullptr);
63 }
64
65 protected:
66 int32_t mConnectCounter;
67 std::shared_ptr<vibrator::MockHalWrapper> mMockHal;
68 std::unique_ptr<vibrator::HalController> mController;
69 };
70
71 // -------------------------------------------------------------------------------------------------
72
TEST_F(VibratorHalControllerTest,TestInit)73 TEST_F(VibratorHalControllerTest, TestInit) {
74 ASSERT_TRUE(mController->init());
75 ASSERT_EQ(1, mConnectCounter);
76
77 // Noop when wrapper was already initialized.
78 ASSERT_TRUE(mController->init());
79 ASSERT_EQ(1, mConnectCounter);
80 }
81
TEST_F(VibratorHalControllerTest,TestGetInfoRetriesOnTransactionFailure)82 TEST_F(VibratorHalControllerTest, TestGetInfoRetriesOnTransactionFailure) {
83 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
84 EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal())
85 .Times(Exactly(2))
86 .WillOnce(Return(vibrator::HalResult<vibrator::Capabilities>::transactionFailed("msg")))
87 .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::ok(
88 vibrator::Capabilities::ON_CALLBACK)));
89
90 auto result = mController->getInfo();
91 ASSERT_TRUE(result.capabilities.isOk());
92 ASSERT_EQ(1, mConnectCounter);
93 }
94
TEST_F(VibratorHalControllerTest,TestGetInfoDoesNotRetryOnOperationFailure)95 TEST_F(VibratorHalControllerTest, TestGetInfoDoesNotRetryOnOperationFailure) {
96 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
97 EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal())
98 .Times(Exactly(1))
99 .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::failed("msg")));
100
101 auto result = mController->getInfo();
102 ASSERT_TRUE(result.capabilities.isFailed());
103 ASSERT_EQ(1, mConnectCounter);
104 }
105
TEST_F(VibratorHalControllerTest,TestGetInfoDoesNotRetryOnUnsupported)106 TEST_F(VibratorHalControllerTest, TestGetInfoDoesNotRetryOnUnsupported) {
107 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
108 EXPECT_CALL(*mMockHal.get(), getCapabilitiesInternal())
109 .Times(Exactly(1))
110 .WillRepeatedly(Return(vibrator::HalResult<vibrator::Capabilities>::unsupported()));
111
112 auto result = mController->getInfo();
113 ASSERT_TRUE(result.capabilities.isUnsupported());
114 ASSERT_EQ(1, mConnectCounter);
115 }
116
TEST_F(VibratorHalControllerTest,TestApiCallsAreForwardedToHal)117 TEST_F(VibratorHalControllerTest, TestApiCallsAreForwardedToHal) {
118 EXPECT_CALL(*mMockHal.get(), on(_, _))
119 .Times(Exactly(1))
120 .WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
121
122 auto result = mController->doWithRetry<void>(ON_FN, "on");
123 ASSERT_TRUE(result.isOk());
124 ASSERT_EQ(1, mConnectCounter);
125 }
126
TEST_F(VibratorHalControllerTest,TestUnsupportedApiResultDoesNotResetHalConnection)127 TEST_F(VibratorHalControllerTest, TestUnsupportedApiResultDoesNotResetHalConnection) {
128 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
129 EXPECT_CALL(*mMockHal.get(), off())
130 .Times(Exactly(1))
131 .WillRepeatedly(Return(vibrator::HalResult<void>::unsupported()));
132
133 auto result = mController->doWithRetry<void>(OFF_FN, "off");
134 ASSERT_TRUE(result.isUnsupported());
135 ASSERT_EQ(1, mConnectCounter);
136 }
137
TEST_F(VibratorHalControllerTest,TestOperationFailedApiResultDoesNotResetHalConnection)138 TEST_F(VibratorHalControllerTest, TestOperationFailedApiResultDoesNotResetHalConnection) {
139 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
140 EXPECT_CALL(*mMockHal.get(), on(_, _))
141 .Times(Exactly(1))
142 .WillRepeatedly(Return(vibrator::HalResult<void>::failed("message")));
143
144 auto result = mController->doWithRetry<void>(ON_FN, "on");
145 ASSERT_TRUE(result.isFailed());
146 ASSERT_EQ(1, mConnectCounter);
147 }
148
TEST_F(VibratorHalControllerTest,TestTransactionFailedApiResultResetsHalConnection)149 TEST_F(VibratorHalControllerTest, TestTransactionFailedApiResultResetsHalConnection) {
150 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
151 EXPECT_CALL(*mMockHal.get(), on(_, _))
152 .Times(Exactly(2))
153 .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
154
155 auto result = mController->doWithRetry<void>(ON_FN, "on");
156 ASSERT_TRUE(result.isFailed());
157 ASSERT_EQ(1, mConnectCounter);
158 }
159
TEST_F(VibratorHalControllerTest,TestTransactionFailedApiResultReturnsSuccessAfterRetries)160 TEST_F(VibratorHalControllerTest, TestTransactionFailedApiResultReturnsSuccessAfterRetries) {
161 {
162 InSequence seq;
163 EXPECT_CALL(*mMockHal.get(), ping())
164 .Times(Exactly(1))
165 .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
166 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
167 EXPECT_CALL(*mMockHal.get(), ping())
168 .Times(Exactly(1))
169 .WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
170 }
171
172 auto result = mController->doWithRetry<void>(PING_FN, "ping");
173 ASSERT_TRUE(result.isOk());
174 ASSERT_EQ(1, mConnectCounter);
175 }
176
TEST_F(VibratorHalControllerTest,TestMultiThreadConnectsOnlyOnce)177 TEST_F(VibratorHalControllerTest, TestMultiThreadConnectsOnlyOnce) {
178 ASSERT_EQ(0, mConnectCounter);
179
180 EXPECT_CALL(*mMockHal.get(), ping())
181 .Times(Exactly(10))
182 .WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
183
184 std::vector<std::thread> threads;
185 for (int i = 0; i < 10; i++) {
186 threads.push_back(std::thread([&]() {
187 auto result = mController->doWithRetry<void>(PING_FN, "ping");
188 ASSERT_TRUE(result.isOk());
189 }));
190 }
191 std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
192
193 // Connector was called only by the first thread to use the api.
194 ASSERT_EQ(1, mConnectCounter);
195 }
196
TEST_F(VibratorHalControllerTest,TestNoVibratorReturnsUnsupportedAndAttemptsToReconnect)197 TEST_F(VibratorHalControllerTest, TestNoVibratorReturnsUnsupportedAndAttemptsToReconnect) {
198 mController = std::make_unique<
199 vibrator::HalController>(nullptr, [&](std::shared_ptr<vibrator::CallbackScheduler>) {
200 android_atomic_inc(&(this->mConnectCounter));
201 return nullptr;
202 });
203 ASSERT_EQ(0, mConnectCounter);
204
205 ASSERT_TRUE(mController->doWithRetry<void>(OFF_FN, "off").isUnsupported());
206 ASSERT_TRUE(mController->doWithRetry<void>(PING_FN, "ping").isUnsupported());
207
208 // One connection attempt per api call.
209 ASSERT_EQ(2, mConnectCounter);
210 }
211
TEST_F(VibratorHalControllerTest,TestScheduledCallbackSurvivesReconnection)212 TEST_F(VibratorHalControllerTest, TestScheduledCallbackSurvivesReconnection) {
213 {
214 InSequence seq;
215 EXPECT_CALL(*mMockHal.get(), on(_, _))
216 .Times(Exactly(1))
217 .WillRepeatedly([&](milliseconds timeout, std::function<void()> callback) {
218 mMockHal.get()->getCallbackScheduler()->schedule(callback, timeout);
219 return vibrator::HalResult<void>::ok();
220 });
221 EXPECT_CALL(*mMockHal.get(), ping())
222 .Times(Exactly(1))
223 .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
224 EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
225 EXPECT_CALL(*mMockHal.get(), ping())
226 .Times(Exactly(1))
227 .WillRepeatedly(Return(vibrator::HalResult<void>::transactionFailed("message")));
228 }
229
230 auto counter = vibrator::TestCounter(0);
231
232 auto onFn = [&](vibrator::HalWrapper* hal) {
233 return hal->on(10ms, [&counter] { counter.increment(); });
234 };
235 ASSERT_TRUE(mController->doWithRetry<void>(onFn, "on").isOk());
236 ASSERT_TRUE(mController->doWithRetry<void>(PING_FN, "ping").isFailed());
237 mMockHal.reset();
238 ASSERT_EQ(0, counter.get());
239
240 // Callback triggered even after HalWrapper was reconnected.
241 counter.tryWaitUntilCountIsAtLeast(1, 500ms);
242 ASSERT_EQ(1, counter.get());
243 }
244