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