1 /*
2 * Copyright (C) 2022 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 "HidlHalPropValue.h"
18 #include "HidlVhalClient.h"
19
20 #include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
21 #include <android-base/result.h>
22 #include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
23 #include <gtest/gtest.h>
24 #include <utils/StrongPointer.h>
25
26 #include <VehicleUtils.h>
27
28 #include <vector>
29
30 namespace android {
31 namespace frameworks {
32 namespace automotive {
33 namespace vhal {
34 namespace hidl_test {
35
36 using ::android::sp;
37 using ::android::hardware::hidl_vec;
38 using ::android::hardware::Return;
39 using ::android::hardware::automotive::vehicle::toInt;
40 using ::android::hardware::automotive::vehicle::VhalResult;
41 using ::android::hardware::automotive::vehicle::V2_0::IVehicle;
42 using ::android::hardware::automotive::vehicle::V2_0::IVehicleCallback;
43 using ::android::hardware::automotive::vehicle::V2_0::StatusCode;
44 using ::android::hardware::automotive::vehicle::V2_0::SubscribeFlags;
45 using ::android::hardware::automotive::vehicle::V2_0::SubscribeOptions;
46 using ::android::hardware::automotive::vehicle::V2_0::VehiclePropConfig;
47 using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValue;
48
49 class MockVhal final : public IVehicle {
50 public:
getAllPropConfigs(IVehicle::getAllPropConfigs_cb callback)51 Return<void> getAllPropConfigs(IVehicle::getAllPropConfigs_cb callback) override {
52 callback(mPropConfigs);
53 return {};
54 }
55
getPropConfigs(const hidl_vec<int32_t> & props,IVehicle::getPropConfigs_cb callback)56 Return<void> getPropConfigs(const hidl_vec<int32_t>& props,
57 IVehicle::getPropConfigs_cb callback) override {
58 mGetPropConfigsProps = props;
59 callback(mStatus, mPropConfigs);
60 return {};
61 }
62
get(const VehiclePropValue & requestPropValue,IVehicle::get_cb callback)63 Return<void> get(const VehiclePropValue& requestPropValue, IVehicle::get_cb callback) override {
64 mRequestPropValue = requestPropValue;
65 callback(mStatus, mPropValue);
66 return {};
67 }
68
set(const VehiclePropValue & value)69 Return<StatusCode> set(const VehiclePropValue& value) override {
70 mRequestPropValue = value;
71 return mStatus;
72 }
73
subscribe(const sp<IVehicleCallback> & callback,const hidl_vec<SubscribeOptions> & options)74 Return<StatusCode> subscribe(const sp<IVehicleCallback>& callback,
75 const hidl_vec<SubscribeOptions>& options) override {
76 mSubscribedCallback = callback;
77 mSubscribeOptions = options;
78 return mStatus;
79 }
80
unsubscribe(const sp<IVehicleCallback> & callback,int32_t propId)81 Return<StatusCode> unsubscribe([[maybe_unused]] const sp<IVehicleCallback>& callback,
82 int32_t propId) override {
83 mUnsubscribedPropId = propId;
84 return mStatus;
85 }
86
debugDump(IVehicle::debugDump_cb callback)87 Return<void> debugDump([[maybe_unused]] IVehicle::debugDump_cb callback) override { return {}; }
88
89 // Test functions
90
setPropConfigs(std::vector<VehiclePropConfig> configs)91 void setPropConfigs(std::vector<VehiclePropConfig> configs) { mPropConfigs = configs; }
92
setStatus(StatusCode status)93 void setStatus(StatusCode status) { mStatus = status; }
94
setVehiclePropValue(VehiclePropValue value)95 void setVehiclePropValue(VehiclePropValue value) { mPropValue = value; }
96
getGetPropConfigsProps()97 std::vector<int32_t> getGetPropConfigsProps() { return mGetPropConfigsProps; }
98
getRequestPropValue()99 VehiclePropValue getRequestPropValue() { return mRequestPropValue; }
100
getSubscribeOptions()101 std::vector<SubscribeOptions> getSubscribeOptions() { return mSubscribeOptions; }
102
getUnsubscribedPropId()103 int32_t getUnsubscribedPropId() { return mUnsubscribedPropId; }
104
triggerOnPropertyEvent(const std::vector<VehiclePropValue> & values)105 void triggerOnPropertyEvent(const std::vector<VehiclePropValue>& values) {
106 mSubscribedCallback->onPropertyEvent(values);
107 }
108
triggerSetErrorEvent(StatusCode status,int32_t propId,int32_t areaId)109 void triggerSetErrorEvent(StatusCode status, int32_t propId, int32_t areaId) {
110 mSubscribedCallback->onPropertySetError(status, propId, areaId);
111 }
112
113 private:
114 std::vector<VehiclePropConfig> mPropConfigs;
115 StatusCode mStatus = StatusCode::OK;
116 VehiclePropValue mPropValue;
117
118 std::vector<int32_t> mGetPropConfigsProps;
119 VehiclePropValue mRequestPropValue;
120 sp<IVehicleCallback> mSubscribedCallback;
121 std::vector<SubscribeOptions> mSubscribeOptions;
122 int32_t mUnsubscribedPropId;
123 };
124
125 class MockSubscriptionCallback final : public ISubscriptionCallback {
126 public:
onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>> & values)127 void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) override {
128 for (const auto& value : values) {
129 mEventPropIds.push_back(value->getPropId());
130 }
131 }
onPropertySetError(const std::vector<HalPropError> & errors)132 void onPropertySetError(const std::vector<HalPropError>& errors) override { mErrors = errors; }
133
getEventPropIds()134 std::vector<int32_t> getEventPropIds() { return mEventPropIds; }
135
getErrors()136 std::vector<HalPropError> getErrors() { return mErrors; }
137
138 private:
139 std::vector<int32_t> mEventPropIds;
140 std::vector<HalPropError> mErrors;
141 };
142
143 class HidlVhalClientTest : public ::testing::Test {
144 protected:
145 constexpr static int32_t TEST_PROP_ID = 1;
146 constexpr static int32_t TEST_AREA_ID = 2;
147 constexpr static int32_t TEST_PROP_ID_2 = 3;
148
149 const VehiclePropValue TEST_VALUE{
150 .prop = TEST_PROP_ID,
151 .areaId = TEST_AREA_ID,
152 .value.int32Values = {1},
153 };
154
SetUp()155 void SetUp() override {
156 mVhal = new MockVhal();
157 mVhalClient = std::make_unique<HidlVhalClient>(mVhal);
158 }
159
getVhal()160 MockVhal* getVhal() { return mVhal.get(); }
161
getClient()162 HidlVhalClient* getClient() { return mVhalClient.get(); }
163
triggerBinderDied()164 void triggerBinderDied() { mVhalClient->onBinderDied(); }
165
166 private:
167 sp<MockVhal> mVhal;
168 std::unique_ptr<HidlVhalClient> mVhalClient;
169 };
170
TEST_F(HidlVhalClientTest,testIsAidl)171 TEST_F(HidlVhalClientTest, testIsAidl) {
172 ASSERT_FALSE(getClient()->isAidlVhal());
173 }
174
TEST_F(HidlVhalClientTest,testGetValue)175 TEST_F(HidlVhalClientTest, testGetValue) {
176 VhalResult<std::unique_ptr<IHalPropValue>> result;
177 VhalResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
178 bool gotResult = false;
179 bool* gotResultPtr = &gotResult;
180 auto callback = std::make_shared<HidlVhalClient::GetValueCallbackFunc>(
181 [resultPtr, gotResultPtr](VhalResult<std::unique_ptr<IHalPropValue>> r) {
182 *resultPtr = std::move(r);
183 *gotResultPtr = true;
184 });
185 getVhal()->setVehiclePropValue(TEST_VALUE);
186
187 getClient()->getValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
188
189 ASSERT_TRUE(gotResult);
190 ASSERT_EQ(getVhal()->getRequestPropValue().prop, TEST_PROP_ID);
191 ASSERT_EQ(getVhal()->getRequestPropValue().areaId, TEST_AREA_ID);
192 ASSERT_TRUE(result.ok());
193 auto gotValue = std::move(result.value());
194 ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
195 ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
196 ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
197 }
198
TEST_F(HidlVhalClientTest,testGetValueError)199 TEST_F(HidlVhalClientTest, testGetValueError) {
200 getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
201
202 VhalResult<std::unique_ptr<IHalPropValue>> result;
203 VhalResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
204 bool gotResult = false;
205 bool* gotResultPtr = &gotResult;
206 auto callback = std::make_shared<HidlVhalClient::GetValueCallbackFunc>(
207 [resultPtr, gotResultPtr](VhalResult<std::unique_ptr<IHalPropValue>> r) {
208 *resultPtr = std::move(r);
209 *gotResultPtr = true;
210 });
211
212 getClient()->getValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
213
214 ASSERT_TRUE(gotResult);
215 ASSERT_FALSE(result.ok());
216 }
217
TEST_F(HidlVhalClientTest,testSetValue)218 TEST_F(HidlVhalClientTest, testSetValue) {
219 VhalResult<void> result;
220 VhalResult<void>* resultPtr = &result;
221 bool gotResult = false;
222 bool* gotResultPtr = &gotResult;
223 auto callback = std::make_shared<HidlVhalClient::SetValueCallbackFunc>(
224 [resultPtr, gotResultPtr](VhalResult<void> r) {
225 *resultPtr = std::move(r);
226 *gotResultPtr = true;
227 });
228
229 getClient()->setValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
230
231 ASSERT_TRUE(gotResult);
232 ASSERT_EQ(getVhal()->getRequestPropValue().prop, TEST_PROP_ID);
233 ASSERT_EQ(getVhal()->getRequestPropValue().areaId, TEST_AREA_ID);
234 ASSERT_TRUE(result.ok());
235 }
TEST_F(HidlVhalClientTest,testSetValueError)236 TEST_F(HidlVhalClientTest, testSetValueError) {
237 getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
238
239 VhalResult<void> result;
240 VhalResult<void>* resultPtr = &result;
241 bool gotResult = false;
242 bool* gotResultPtr = &gotResult;
243 auto callback = std::make_shared<HidlVhalClient::SetValueCallbackFunc>(
244 [resultPtr, gotResultPtr](VhalResult<void> r) {
245 *resultPtr = std::move(r);
246 *gotResultPtr = true;
247 });
248
249 getClient()->setValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
250
251 ASSERT_TRUE(gotResult);
252 ASSERT_FALSE(result.ok());
253 }
254
TEST_F(HidlVhalClientTest,testAddOnBinderDiedCallback)255 TEST_F(HidlVhalClientTest, testAddOnBinderDiedCallback) {
256 struct Result {
257 bool callbackOneCalled = false;
258 bool callbackTwoCalled = false;
259 } result;
260
261 getClient()->addOnBinderDiedCallback(std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
262 [&result] { result.callbackOneCalled = true; }));
263 getClient()->addOnBinderDiedCallback(std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
264 [&result] { result.callbackTwoCalled = true; }));
265 triggerBinderDied();
266
267 ASSERT_TRUE(result.callbackOneCalled);
268 ASSERT_TRUE(result.callbackTwoCalled);
269 }
270
TEST_F(HidlVhalClientTest,testRemoveOnBinderDiedCallback)271 TEST_F(HidlVhalClientTest, testRemoveOnBinderDiedCallback) {
272 struct Result {
273 bool callbackOneCalled = false;
274 bool callbackTwoCalled = false;
275 } result;
276
277 auto callbackOne = std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
278 [&result] { result.callbackOneCalled = true; });
279 auto callbackTwo = std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
280 [&result] { result.callbackTwoCalled = true; });
281 getClient()->addOnBinderDiedCallback(callbackOne);
282 getClient()->addOnBinderDiedCallback(callbackTwo);
283 getClient()->removeOnBinderDiedCallback(callbackOne);
284 triggerBinderDied();
285
286 ASSERT_FALSE(result.callbackOneCalled);
287 ASSERT_TRUE(result.callbackTwoCalled);
288 }
289
TEST_F(HidlVhalClientTest,testGetAllPropConfigs)290 TEST_F(HidlVhalClientTest, testGetAllPropConfigs) {
291 getVhal()->setPropConfigs({
292 VehiclePropConfig{
293 .prop = TEST_PROP_ID,
294 .areaConfigs = {{
295 .areaId = TEST_AREA_ID,
296 .minInt32Value = 0,
297 .maxInt32Value = 1,
298 }},
299 },
300 VehiclePropConfig{
301 .prop = TEST_PROP_ID_2,
302 },
303 });
304
305 auto result = getClient()->getAllPropConfigs();
306
307 ASSERT_TRUE(result.ok());
308 std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
309
310 ASSERT_EQ(configs.size(), static_cast<size_t>(2));
311 ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
312 ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(1));
313
314 const IHalAreaConfig* areaConfig = configs[0]->getAreaConfigs();
315 ASSERT_EQ(areaConfig->getAreaId(), TEST_AREA_ID);
316 ASSERT_EQ(areaConfig->getMinInt32Value(), 0);
317 ASSERT_EQ(areaConfig->getMaxInt32Value(), 1);
318
319 ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
320 ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(0));
321 }
322
TEST_F(HidlVhalClientTest,testGetPropConfigs)323 TEST_F(HidlVhalClientTest, testGetPropConfigs) {
324 getVhal()->setPropConfigs({
325 VehiclePropConfig{
326 .prop = TEST_PROP_ID,
327 .areaConfigs = {{
328 .areaId = TEST_AREA_ID,
329 .minInt32Value = 0,
330 .maxInt32Value = 1,
331 }},
332 },
333 VehiclePropConfig{
334 .prop = TEST_PROP_ID_2,
335 },
336 });
337
338 std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
339 auto result = getClient()->getPropConfigs(propIds);
340
341 ASSERT_EQ(getVhal()->getGetPropConfigsProps(), propIds);
342 ASSERT_TRUE(result.ok());
343 std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
344
345 ASSERT_EQ(configs.size(), static_cast<size_t>(2));
346 ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
347 ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(1));
348
349 const IHalAreaConfig* areaConfig = configs[0]->getAreaConfigs();
350 ASSERT_EQ(areaConfig->getAreaId(), TEST_AREA_ID);
351 ASSERT_EQ(areaConfig->getMinInt32Value(), 0);
352 ASSERT_EQ(areaConfig->getMaxInt32Value(), 1);
353
354 ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
355 ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(0));
356 }
357
TEST_F(HidlVhalClientTest,testGetPropConfigsError)358 TEST_F(HidlVhalClientTest, testGetPropConfigsError) {
359 getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
360
361 std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
362 auto result = getClient()->getPropConfigs(propIds);
363
364 ASSERT_FALSE(result.ok());
365 }
366
TEST_F(HidlVhalClientTest,testSubscribe)367 TEST_F(HidlVhalClientTest, testSubscribe) {
368 std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions> options = {
369 {
370 .propId = TEST_PROP_ID,
371 .areaIds = {TEST_AREA_ID},
372 .sampleRate = 1.0,
373 },
374 {
375 .propId = TEST_PROP_ID_2,
376 .sampleRate = 2.0,
377 },
378 };
379 std::vector<SubscribeOptions> hidlOptions = {
380 {
381 .propId = TEST_PROP_ID,
382 .flags = SubscribeFlags::EVENTS_FROM_CAR,
383 .sampleRate = 1.0,
384 },
385 {
386 .propId = TEST_PROP_ID_2,
387 .flags = SubscribeFlags::EVENTS_FROM_CAR,
388 .sampleRate = 2.0,
389 },
390 };
391
392 auto callback = std::make_shared<MockSubscriptionCallback>();
393 auto subscriptionClient = getClient()->getSubscriptionClient(callback);
394 auto result = subscriptionClient->subscribe(options);
395
396 ASSERT_TRUE(result.ok());
397 ASSERT_EQ(getVhal()->getSubscribeOptions(), hidlOptions);
398
399 getVhal()->triggerOnPropertyEvent(std::vector<VehiclePropValue>{
400 {
401 .prop = TEST_PROP_ID,
402 .areaId = TEST_AREA_ID,
403 .value.int32Values = {1},
404 },
405 });
406
407 ASSERT_EQ(callback->getEventPropIds(), std::vector<int32_t>({TEST_PROP_ID}));
408
409 getVhal()->triggerSetErrorEvent(StatusCode::INTERNAL_ERROR, TEST_PROP_ID, TEST_AREA_ID);
410
411 auto errors = callback->getErrors();
412 ASSERT_EQ(errors.size(), static_cast<size_t>(1));
413 ASSERT_EQ(errors[0].propId, TEST_PROP_ID);
414 ASSERT_EQ(errors[0].areaId, TEST_AREA_ID);
415 ASSERT_EQ(errors[0].status,
416 ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
417 }
418
TEST_F(HidlVhalClientTest,testSubscribeError)419 TEST_F(HidlVhalClientTest, testSubscribeError) {
420 std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions> options = {
421 {
422 .propId = TEST_PROP_ID,
423 .areaIds = {TEST_AREA_ID},
424 .sampleRate = 1.0,
425 },
426 {
427 .propId = TEST_PROP_ID_2,
428 .sampleRate = 2.0,
429 },
430 };
431
432 getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
433 auto callback = std::make_shared<MockSubscriptionCallback>();
434 auto subscriptionClient = getClient()->getSubscriptionClient(callback);
435 auto result = subscriptionClient->subscribe(options);
436
437 ASSERT_FALSE(result.ok());
438 }
439
TEST_F(HidlVhalClientTest,testUnubscribe)440 TEST_F(HidlVhalClientTest, testUnubscribe) {
441 auto callback = std::make_shared<MockSubscriptionCallback>();
442 auto subscriptionClient = getClient()->getSubscriptionClient(callback);
443 auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
444
445 ASSERT_TRUE(result.ok());
446 ASSERT_EQ(getVhal()->getUnsubscribedPropId(), TEST_PROP_ID);
447 }
448
TEST_F(HidlVhalClientTest,testUnubscribeError)449 TEST_F(HidlVhalClientTest, testUnubscribeError) {
450 getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
451 auto callback = std::make_shared<MockSubscriptionCallback>();
452 auto subscriptionClient = getClient()->getSubscriptionClient(callback);
453 auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
454
455 ASSERT_FALSE(result.ok());
456 }
457
458 } // namespace hidl_test
459 } // namespace vhal
460 } // namespace automotive
461 } // namespace frameworks
462 } // namespace android
463