• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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