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