xref: /aosp_15_r20/frameworks/native/services/vibratorservice/test/VibratorHalControllerTest.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 "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