1 /*
2 * Copyright (C) 2019 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 #include <android-base/logging.h>
18 #include <android-base/strings.h>
19 #include <android/hardware/automotive/can/1.0/ICanBus.h>
20 #include <android/hardware/automotive/can/1.0/types.h>
21 #include <can-vts-utils/bus-enumerator.h>
22 #include <can-vts-utils/can-hal-printers.h>
23 #include <gmock/gmock.h>
24 #include <hidl-utils/hidl-utils.h>
25 #include <hidl/GtestPrinter.h>
26 #include <hidl/ServiceManagement.h>
27
28 namespace android::hardware::automotive::can::V1_0::vts {
29
30 using hardware::hidl_vec;
31 using InterfaceType = ICanController::InterfaceType;
32 using IfId = ICanController::BusConfig::InterfaceId;
33
34 struct CanMessageListener : public can::V1_0::ICanMessageListener {
onReceiveandroid::hardware::automotive::can::V1_0::vts::CanMessageListener35 virtual Return<void> onReceive(const can::V1_0::CanMessage&) override { return {}; }
36 };
37
38 struct CanErrorListener : public can::V1_0::ICanErrorListener {
onErrorandroid::hardware::automotive::can::V1_0::vts::CanErrorListener39 virtual Return<void> onError(ErrorEvent, bool) override { return {}; }
40 };
41
42 class CanBusHalTest : public ::testing::TestWithParam<std::string> {
43 protected:
44 virtual void SetUp() override;
45 virtual void TearDown() override;
46
47 bool up(InterfaceType iftype, const std::string& srvname, const std::string& ifname);
48
49 std::tuple<Result, sp<ICloseHandle>> listen(const hidl_vec<CanMessageFilter>& filter,
50 const sp<ICanMessageListener>& listener);
51 sp<ICloseHandle> listenForErrors(const sp<ICanErrorListener>& listener);
52
53 sp<ICanBus> mCanBus;
54 sp<ICanController> mCanController;
55 };
56
SetUp()57 void CanBusHalTest::SetUp() {
58 mCanBus = ICanBus::getService(GetParam());
59 ASSERT_TRUE(mCanBus) << "Couldn't open CAN Bus: " << GetParam();
60 const auto controllers = getAllHalInstanceNames(ICanController::descriptor);
61 ASSERT_GT(controllers.size(), 0u);
62 // just grab the first one
63 mCanController = ICanController::getService(controllers[0]);
64 ASSERT_TRUE(mCanController) << "Couldn't open CAN Controller: " << controllers[0];
65
66 // this will throw an error if the bus is already up, but we have to try.
67 up(InterfaceType::VIRTUAL, GetParam(), "vcan0");
68 }
69
TearDown()70 void CanBusHalTest::TearDown() {
71 mCanBus.clear();
72 }
73
up(InterfaceType iftype,const std::string & srvname,const std::string & ifname)74 bool CanBusHalTest::up(InterfaceType iftype, const std::string& srvname,
75 const std::string& ifname) {
76 ICanController::BusConfig config = {};
77 config.name = srvname;
78
79 // TODO(b/146214370): move interfaceId constructors to a library
80 if (iftype == InterfaceType::SOCKETCAN) {
81 IfId::Socketcan socketcan = {};
82 socketcan.ifname(ifname);
83 config.interfaceId.socketcan(socketcan);
84 } else if (iftype == InterfaceType::SLCAN) {
85 IfId::Slcan slcan = {};
86 slcan.ttyname(ifname);
87 config.interfaceId.slcan(slcan);
88 } else if (iftype == InterfaceType::VIRTUAL) {
89 config.interfaceId.virtualif({ifname});
90 } else {
91 ADD_FAILURE() << "Unexpected iftype: " << toString(iftype);
92 }
93
94 const auto upresult = mCanController->upInterface(config);
95 if (upresult != ICanController::Result::OK) {
96 // upInterface returns INVALID_STATE if the interface is already up (which is fine).
97 EXPECT_EQ(ICanController::Result::INVALID_STATE, upresult)
98 << ifname << " can't be brought up!";
99 }
100 return true;
101 }
102
listen(const hidl_vec<CanMessageFilter> & filter,const sp<ICanMessageListener> & listener)103 std::tuple<Result, sp<ICloseHandle>> CanBusHalTest::listen(
104 const hidl_vec<CanMessageFilter>& filter, const sp<ICanMessageListener>& listener) {
105 Result halResult;
106 sp<ICloseHandle> closeHandle;
107 mCanBus->listen(filter, listener, hidl_utils::fill(&halResult, &closeHandle)).assertOk();
108
109 return {halResult, closeHandle};
110 }
111
listenForErrors(const sp<ICanErrorListener> & listener)112 sp<ICloseHandle> CanBusHalTest::listenForErrors(const sp<ICanErrorListener>& listener) {
113 const auto res = mCanBus->listenForErrors(listener);
114 res.assertOk();
115 return res;
116 }
117
TEST_P(CanBusHalTest,SendNoPayload)118 TEST_P(CanBusHalTest, SendNoPayload) {
119 CanMessage msg = {};
120 msg.id = 0x123;
121 ASSERT_NE(mCanBus, nullptr);
122 const auto result = mCanBus->send(msg);
123 ASSERT_EQ(Result::OK, result);
124 }
125
TEST_P(CanBusHalTest,Send8B)126 TEST_P(CanBusHalTest, Send8B) {
127 CanMessage msg = {};
128 msg.id = 0x234;
129 msg.payload = {1, 2, 3, 4, 5, 6, 7, 8};
130
131 const auto result = mCanBus->send(msg);
132 ASSERT_EQ(Result::OK, result);
133 }
134
TEST_P(CanBusHalTest,SendZeroId)135 TEST_P(CanBusHalTest, SendZeroId) {
136 CanMessage msg = {};
137 msg.payload = {1, 2, 3};
138
139 const auto result = mCanBus->send(msg);
140 ASSERT_EQ(Result::OK, result);
141 }
142
TEST_P(CanBusHalTest,SendTooLong)143 TEST_P(CanBusHalTest, SendTooLong) {
144 CanMessage msg = {};
145 msg.id = 0x123;
146 msg.payload = hidl_vec<uint8_t>(102400); // 100kiB
147
148 const auto result = mCanBus->send(msg);
149 ASSERT_EQ(Result::PAYLOAD_TOO_LONG, result);
150 }
151
TEST_P(CanBusHalTest,ListenNoFilter)152 TEST_P(CanBusHalTest, ListenNoFilter) {
153 const auto [result, closeHandle] = listen({}, new CanMessageListener());
154 ASSERT_EQ(Result::OK, result);
155
156 closeHandle->close().assertOk();
157 }
158
TEST_P(CanBusHalTest,ListenSomeFilter)159 TEST_P(CanBusHalTest, ListenSomeFilter) {
160 hidl_vec<CanMessageFilter> filters = {
161 {0x123, 0x1FF, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE, false},
162 {0x001, 0x00F, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE, true},
163 {0x200, 0x100, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE, false},
164 };
165
166 const auto [result, closeHandle] = listen(filters, new CanMessageListener());
167 ASSERT_EQ(Result::OK, result);
168
169 closeHandle->close().assertOk();
170 }
171
TEST_P(CanBusHalTest,ListenNull)172 TEST_P(CanBusHalTest, ListenNull) {
173 const auto [result, closeHandle] = listen({}, nullptr);
174 ASSERT_EQ(Result::INVALID_ARGUMENTS, result);
175 }
176
TEST_P(CanBusHalTest,DoubleCloseListener)177 TEST_P(CanBusHalTest, DoubleCloseListener) {
178 const auto [result, closeHandle] = listen({}, new CanMessageListener());
179 ASSERT_EQ(Result::OK, result);
180
181 closeHandle->close().assertOk();
182 closeHandle->close().assertOk();
183 }
184
TEST_P(CanBusHalTest,DontCloseListener)185 TEST_P(CanBusHalTest, DontCloseListener) {
186 const auto [result, closeHandle] = listen({}, new CanMessageListener());
187 ASSERT_EQ(Result::OK, result);
188 }
189
TEST_P(CanBusHalTest,DoubleCloseErrorListener)190 TEST_P(CanBusHalTest, DoubleCloseErrorListener) {
191 auto closeHandle = listenForErrors(new CanErrorListener());
192 ASSERT_NE(nullptr, closeHandle.get());
193
194 closeHandle->close().assertOk();
195 closeHandle->close().assertOk();
196 }
197
TEST_P(CanBusHalTest,DoubleCloseNullErrorListener)198 TEST_P(CanBusHalTest, DoubleCloseNullErrorListener) {
199 auto closeHandle = listenForErrors(nullptr);
200 ASSERT_NE(nullptr, closeHandle.get());
201
202 closeHandle->close().assertOk();
203 closeHandle->close().assertOk();
204 }
205
TEST_P(CanBusHalTest,DontCloseErrorListener)206 TEST_P(CanBusHalTest, DontCloseErrorListener) {
207 auto closeHandle = listenForErrors(new CanErrorListener());
208 ASSERT_NE(nullptr, closeHandle.get());
209 }
210
211 /**
212 * This test requires that you bring up a valid bus first.
213 *
214 * Before running:
215 * mma -j && adb root && adb remount && adb sync
216 *
217 * Example manual invocation:
218 * adb shell canhalctrl up <NAME_OF_VALID_BUS> socketcan can0 125000
219 * adb shell /data/nativetest64/VtsHalCanBusV1_0TargetTest/VtsHalCanBusV1_0TargetTest\
220 * --gtest_filter=*_<NAME_OF_VALID_BUS>
221 */
222 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CanBusHalTest);
223 INSTANTIATE_TEST_SUITE_P(PerInstance, CanBusHalTest,
224 testing::ValuesIn(getAllHalInstanceNames(ICanBus::descriptor)),
225 PrintInstanceNameToString);
226
227 } // namespace android::hardware::automotive::can::V1_0::vts
228