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 <aidl/android/hardware/automotive/vehicle/BnVehicle.h>
18 #include <android/binder_ibinder.h>
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <AidlHalPropValue.h>
23 #include <AidlVhalClient.h>
24 #include <VehicleHalTypes.h>
25 #include <VehicleUtils.h>
26 
27 #include <atomic>
28 #include <condition_variable>  // NOLINT
29 #include <mutex>               // NOLINT
30 #include <thread>              // NOLINT
31 
32 namespace android {
33 namespace frameworks {
34 namespace automotive {
35 namespace vhal {
36 namespace aidl_test {
37 
38 using ::android::hardware::automotive::vehicle::toInt;
39 
40 using ::aidl::android::hardware::automotive::vehicle::BnVehicle;
41 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
42 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
43 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
44 using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
45 using ::aidl::android::hardware::automotive::vehicle::IVehicle;
46 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
47 using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResults;
48 using ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;
49 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
50 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
51 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
52 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
53 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
54 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
55 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
56 using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResults;
57 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
58 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
59 using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
60 using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
61 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
62 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
63 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
64 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
65 
66 using ::ndk::ScopedAStatus;
67 using ::ndk::SharedRefBase;
68 using ::testing::Gt;
69 
70 class MockVhal final : public BnVehicle {
71 public:
72     using CallbackType = std::shared_ptr<IVehicleCallback>;
73 
~MockVhal()74     ~MockVhal() {
75         std::unique_lock<std::mutex> lk(mLock);
76         mCv.wait_for(lk, std::chrono::milliseconds(1000), [this] { return mThreadCount == 0; });
77     }
78 
getAllPropConfigs(VehiclePropConfigs * returnConfigs)79     ScopedAStatus getAllPropConfigs(VehiclePropConfigs* returnConfigs) override {
80         if (mStatus != StatusCode::OK) {
81             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
82         }
83 
84         returnConfigs->payloads = mPropConfigs;
85         return ScopedAStatus::ok();
86     }
87 
getValues(const CallbackType & callback,const GetValueRequests & requests)88     ScopedAStatus getValues(const CallbackType& callback,
89                             const GetValueRequests& requests) override {
90         mGetValueRequests = requests.payloads;
91 
92         if (mStatus != StatusCode::OK) {
93             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
94         }
95 
96         if (mWaitTimeInMs == 0) {
97             callback->onGetValues(GetValueResults{.payloads = mGetValueResults});
98         } else {
99             mThreadCount++;
100             std::thread t([this, callback]() {
101                 std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTimeInMs));
102                 callback->onGetValues(GetValueResults{.payloads = mGetValueResults});
103                 mThreadCount--;
104                 mCv.notify_one();
105             });
106             // Detach the thread here so we do not have to maintain the thread object. mThreadCount
107             // and mCv make sure we wait for all threads to end before we exit.
108             t.detach();
109         }
110         return ScopedAStatus::ok();
111     }
112 
setValues(const CallbackType & callback,const SetValueRequests & requests)113     ScopedAStatus setValues(const CallbackType& callback,
114                             const SetValueRequests& requests) override {
115         mSetValueRequests = requests.payloads;
116 
117         if (mStatus != StatusCode::OK) {
118             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
119         }
120 
121         if (mWaitTimeInMs == 0) {
122             callback->onSetValues(SetValueResults{.payloads = mSetValueResults});
123         } else {
124             mThreadCount++;
125             std::thread t([this, callback]() {
126                 std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTimeInMs));
127                 callback->onSetValues(SetValueResults{.payloads = mSetValueResults});
128                 mThreadCount--;
129                 mCv.notify_one();
130             });
131             // Detach the thread here so we do not have to maintain the thread object. mThreadCount
132             // and mCv make sure we wait for all threads to end before we exit.
133             t.detach();
134         }
135         return ScopedAStatus::ok();
136     }
137 
getPropConfigs(const std::vector<int32_t> & props,VehiclePropConfigs * returnConfigs)138     ScopedAStatus getPropConfigs(const std::vector<int32_t>& props,
139                                  VehiclePropConfigs* returnConfigs) override {
140         mGetPropConfigPropIds = props;
141         if (mStatus != StatusCode::OK) {
142             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
143         }
144 
145         returnConfigs->payloads = mPropConfigs;
146         return ScopedAStatus::ok();
147     }
148 
subscribe(const CallbackType & callback,const std::vector<SubscribeOptions> & options,int32_t maxSharedMemoryFileCount)149     ScopedAStatus subscribe(const CallbackType& callback,
150                             const std::vector<SubscribeOptions>& options,
151                             [[maybe_unused]] int32_t maxSharedMemoryFileCount) override {
152         mSubscriptionCallback = callback;
153         mSubscriptionOptions = options;
154 
155         if (mStatus != StatusCode::OK) {
156             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
157         }
158         return ScopedAStatus::ok();
159     }
160 
unsubscribe(const CallbackType & callback,const std::vector<int32_t> & propIds)161     ScopedAStatus unsubscribe([[maybe_unused]] const CallbackType& callback,
162                               const std::vector<int32_t>& propIds) override {
163         mUnsubscribePropIds = propIds;
164 
165         if (mStatus != StatusCode::OK) {
166             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
167         }
168         return ScopedAStatus::ok();
169     }
170 
returnSharedMemory(const CallbackType & callback,int64_t sharedMemoryId)171     ScopedAStatus returnSharedMemory([[maybe_unused]] const CallbackType& callback,
172                                      [[maybe_unused]] int64_t sharedMemoryId) override {
173         return ScopedAStatus::ok();
174     }
175 
getSupportedValuesLists(const std::vector<PropIdAreaId> &,SupportedValuesListResults *)176     ScopedAStatus getSupportedValuesLists(const std::vector<PropIdAreaId>&,
177                                           SupportedValuesListResults*) {
178         return ScopedAStatus::ok();
179     }
180 
getMinMaxSupportedValue(const std::vector<PropIdAreaId> &,MinMaxSupportedValueResults *)181     ScopedAStatus getMinMaxSupportedValue(const std::vector<PropIdAreaId>&,
182                                           MinMaxSupportedValueResults*) {
183         return ScopedAStatus::ok();
184     }
185 
registerSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback> &,const std::vector<PropIdAreaId> &)186     ScopedAStatus registerSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback>&,
187                                                        const std::vector<PropIdAreaId>&) {
188         return ScopedAStatus::ok();
189     }
190 
unregisterSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback> &,const std::vector<PropIdAreaId> &)191     ScopedAStatus unregisterSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback>&,
192                                                          const std::vector<PropIdAreaId>&) {
193         return ScopedAStatus::ok();
194     }
195 
196     // Test Functions
197 
setGetValueResults(std::vector<GetValueResult> results)198     void setGetValueResults(std::vector<GetValueResult> results) { mGetValueResults = results; }
199 
getGetValueRequests()200     std::vector<GetValueRequest> getGetValueRequests() { return mGetValueRequests; }
201 
setSetValueResults(std::vector<SetValueResult> results)202     void setSetValueResults(std::vector<SetValueResult> results) { mSetValueResults = results; }
203 
getSetValueRequests()204     std::vector<SetValueRequest> getSetValueRequests() { return mSetValueRequests; }
205 
setWaitTimeInMs(int64_t waitTimeInMs)206     void setWaitTimeInMs(int64_t waitTimeInMs) { mWaitTimeInMs = waitTimeInMs; }
207 
setStatus(StatusCode status)208     void setStatus(StatusCode status) { mStatus = status; }
209 
setPropConfigs(std::vector<VehiclePropConfig> configs)210     void setPropConfigs(std::vector<VehiclePropConfig> configs) { mPropConfigs = configs; }
211 
getGetPropConfigPropIds()212     std::vector<int32_t> getGetPropConfigPropIds() { return mGetPropConfigPropIds; }
213 
getSubscriptionOptions()214     std::vector<SubscribeOptions> getSubscriptionOptions() { return mSubscriptionOptions; }
215 
triggerOnPropertyEvent(const std::vector<VehiclePropValue> & values)216     void triggerOnPropertyEvent(const std::vector<VehiclePropValue>& values) {
217         VehiclePropValues propValues = {
218                 .payloads = values,
219         };
220         mSubscriptionCallback->onPropertyEvent(propValues, /*sharedMemoryCount=*/0);
221     }
222 
triggerSetErrorEvent(const std::vector<VehiclePropError> & errors)223     void triggerSetErrorEvent(const std::vector<VehiclePropError>& errors) {
224         VehiclePropErrors propErrors = {
225                 .payloads = errors,
226         };
227         mSubscriptionCallback->onPropertySetError(propErrors);
228     }
229 
getUnsubscribedPropIds()230     std::vector<int32_t> getUnsubscribedPropIds() { return mUnsubscribePropIds; }
231 
232 private:
233     std::mutex mLock;
234     std::vector<GetValueResult> mGetValueResults;
235     std::vector<GetValueRequest> mGetValueRequests;
236     std::vector<SetValueResult> mSetValueResults;
237     std::vector<SetValueRequest> mSetValueRequests;
238     std::vector<VehiclePropConfig> mPropConfigs;
239     std::vector<int32_t> mGetPropConfigPropIds;
240     int64_t mWaitTimeInMs = 0;
241     StatusCode mStatus = StatusCode::OK;
242     std::condition_variable mCv;
243     std::atomic<int> mThreadCount = 0;
244     CallbackType mSubscriptionCallback;
245     std::vector<SubscribeOptions> mSubscriptionOptions;
246     std::vector<int32_t> mUnsubscribePropIds;
247 };
248 
249 class MockSubscriptionCallback : public ISubscriptionCallback {
250 public:
onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>> & values)251     void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) override {
252         for (const auto& value : values) {
253             mEventPropIds.push_back(value->getPropId());
254         }
255     }
onPropertySetError(const std::vector<HalPropError> & errors)256     void onPropertySetError(const std::vector<HalPropError>& errors) override { mErrors = errors; }
257 
getEventPropIds()258     std::vector<int32_t> getEventPropIds() { return mEventPropIds; }
259 
getErrors()260     std::vector<HalPropError> getErrors() { return mErrors; }
261 
262 private:
263     std::vector<int32_t> mEventPropIds;
264     std::vector<HalPropError> mErrors;
265 };
266 
267 class AidlVhalClientTest : public ::testing::Test {
268 protected:
269     class TestLinkUnlinkImpl final : public AidlVhalClient::ILinkUnlinkToDeath {
270     public:
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)271         binder_status_t linkToDeath([[maybe_unused]] AIBinder* binder,
272                                     [[maybe_unused]] AIBinder_DeathRecipient* recipient,
273                                     void* cookie) override {
274             mCookie = cookie;
275             mDeathRecipient = recipient;
276             return STATUS_OK;
277         }
278 
deleteDeathRecipient(AIBinder_DeathRecipient * recipient)279         void deleteDeathRecipient(AIBinder_DeathRecipient* recipient) override {
280             if (mDeathRecipient == recipient) {
281                 triggerBinderUnlinked();
282             }
283         }
284 
setOnUnlinked(AIBinder_DeathRecipient * recipient,AIBinder_DeathRecipient_onBinderUnlinked onUnlinked)285         void setOnUnlinked([[maybe_unused]] AIBinder_DeathRecipient* recipient,
286                            AIBinder_DeathRecipient_onBinderUnlinked onUnlinked) override {
287             mOnUnlinked = onUnlinked;
288         }
289 
getCookie()290         void* getCookie() { return mCookie; }
291 
triggerBinderUnlinked()292         void triggerBinderUnlinked() {
293             if (mDeathRecipient == nullptr) {
294                 // Already unlinked, do nothing.
295                 return;
296             }
297             (*mOnUnlinked)(mCookie);
298             mDeathRecipient = nullptr;
299         }
300 
301     private:
302         void* mCookie;
303         AIBinder_DeathRecipient_onBinderUnlinked mOnUnlinked;
304         AIBinder_DeathRecipient* mDeathRecipient;
305     };
306 
307     constexpr static int32_t TEST_PROP_ID = 1;
308     constexpr static int32_t TEST_AREA_ID = 2;
309     constexpr static int32_t TEST_PROP_ID_2 = 3;
310     constexpr static int32_t TEST_AREA_ID_2 = 4;
311     constexpr static VehiclePropertyAccess TEST_GLOBAL_ACCESS = VehiclePropertyAccess::READ_WRITE;
312     constexpr static VehiclePropertyAccess TEST_AREA_ACCESS = VehiclePropertyAccess::READ;
313     constexpr static int64_t TEST_TIMEOUT_IN_MS = 100;
314 
SetUp()315     void SetUp() override {
316         mVhal = SharedRefBase::make<MockVhal>();
317         auto impl = std::make_unique<TestLinkUnlinkImpl>();
318         // We are sure impl would be alive when we use mLinkUnlinkImpl.
319         mLinkUnlinkImpl = impl.get();
320         mVhalClient = std::unique_ptr<AidlVhalClient>(
321                 new AidlVhalClient(mVhal, TEST_TIMEOUT_IN_MS, std::move(impl)));
322     }
323 
getClient()324     AidlVhalClient* getClient() { return mVhalClient.get(); }
325 
resetClient()326     void resetClient() { mVhalClient.reset(); }
327 
getVhal()328     MockVhal* getVhal() { return mVhal.get(); }
329 
triggerBinderDied()330     void triggerBinderDied() {
331         AidlVhalClient::onBinderDied(mLinkUnlinkImpl->getCookie());
332         mLinkUnlinkImpl->triggerBinderUnlinked();
333     }
334 
countOnBinderDiedCallbacks()335     size_t countOnBinderDiedCallbacks() { return mVhalClient->countOnBinderDiedCallbacks(); }
336 
337 private:
338     std::shared_ptr<MockVhal> mVhal;
339     std::unique_ptr<AidlVhalClient> mVhalClient;
340     TestLinkUnlinkImpl* mLinkUnlinkImpl;
341 };
342 
TEST_F(AidlVhalClientTest,testIsAidl)343 TEST_F(AidlVhalClientTest, testIsAidl) {
344     ASSERT_TRUE(getClient()->isAidlVhal());
345 }
346 
TEST_F(AidlVhalClientTest,testGetValueNormal)347 TEST_F(AidlVhalClientTest, testGetValueNormal) {
348     VehiclePropValue testProp{
349             .prop = TEST_PROP_ID,
350             .areaId = TEST_AREA_ID,
351     };
352     getVhal()->setWaitTimeInMs(10);
353     getVhal()->setGetValueResults({
354             GetValueResult{
355                     .requestId = 0,
356                     .status = StatusCode::OK,
357                     .prop =
358                             VehiclePropValue{
359                                     .prop = TEST_PROP_ID,
360                                     .areaId = TEST_AREA_ID,
361                                     .value =
362                                             RawPropValues{
363                                                     .int32Values = {1},
364                                             },
365                             },
366             },
367     });
368 
369     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
370     std::mutex lock;
371     std::condition_variable cv;
372     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
373     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
374     bool gotResult = false;
375     bool* gotResultPtr = &gotResult;
376 
377     auto callback = std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
378             [&lock, &cv, resultPtr,
379              gotResultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
380                 {
381                     std::lock_guard<std::mutex> lockGuard(lock);
382                     *resultPtr = std::move(r);
383                     *gotResultPtr = true;
384                 }
385                 cv.notify_one();
386             });
387     getClient()->getValue(propValue, callback);
388 
389     std::unique_lock<std::mutex> lk(lock);
390     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
391 
392     ASSERT_TRUE(gotResult);
393     ASSERT_EQ(getVhal()->getGetValueRequests(),
394               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
395     ASSERT_TRUE(result.ok());
396     auto gotValue = std::move(result.value());
397     ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
398     ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
399     ASSERT_EQ(gotValue->getStatus(), VehiclePropertyStatus::AVAILABLE);
400     ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
401 }
402 
TEST_F(AidlVhalClientTest,testGetValueSync)403 TEST_F(AidlVhalClientTest, testGetValueSync) {
404     VehiclePropValue testProp{
405             .prop = TEST_PROP_ID,
406             .areaId = TEST_AREA_ID,
407     };
408     getVhal()->setWaitTimeInMs(10);
409     getVhal()->setGetValueResults({
410             GetValueResult{
411                     .requestId = 0,
412                     .status = StatusCode::OK,
413                     .prop =
414                             VehiclePropValue{
415                                     .prop = TEST_PROP_ID,
416                                     .areaId = TEST_AREA_ID,
417                                     .value =
418                                             RawPropValues{
419                                                     .int32Values = {1},
420                                             },
421                             },
422             },
423     });
424 
425     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
426     VhalClientResult<std::unique_ptr<IHalPropValue>> result = getClient()->getValueSync(propValue);
427 
428     ASSERT_EQ(getVhal()->getGetValueRequests(),
429               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
430     ASSERT_TRUE(result.ok());
431     auto gotValue = std::move(result.value());
432     ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
433     ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
434     ASSERT_EQ(gotValue->getStatus(), VehiclePropertyStatus::AVAILABLE);
435     ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
436 }
437 
TEST_F(AidlVhalClientTest,testGetValueUnavailableStatusSync)438 TEST_F(AidlVhalClientTest, testGetValueUnavailableStatusSync) {
439     VehiclePropValue testProp{
440             .prop = TEST_PROP_ID,
441             .areaId = TEST_AREA_ID,
442     };
443     getVhal()->setWaitTimeInMs(10);
444     getVhal()->setGetValueResults({
445             GetValueResult{
446                     .requestId = 0,
447                     .status = StatusCode::OK,
448                     .prop =
449                             VehiclePropValue{
450                                     .prop = TEST_PROP_ID,
451                                     .areaId = TEST_AREA_ID,
452                                     .status = VehiclePropertyStatus::UNAVAILABLE,
453                             },
454             },
455     });
456 
457     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
458     VhalClientResult<std::unique_ptr<IHalPropValue>> result = getClient()->getValueSync(propValue);
459 
460     ASSERT_EQ(getVhal()->getGetValueRequests(),
461               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
462     ASSERT_TRUE(result.ok());
463     auto gotValue = std::move(result.value());
464     ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
465     ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
466     ASSERT_EQ(gotValue->getStatus(), VehiclePropertyStatus::UNAVAILABLE);
467 }
468 
TEST_F(AidlVhalClientTest,testGetValueTimeout)469 TEST_F(AidlVhalClientTest, testGetValueTimeout) {
470     VehiclePropValue testProp{
471             .prop = TEST_PROP_ID,
472             .areaId = TEST_AREA_ID,
473     };
474     // The request will time-out before the response.
475     getVhal()->setWaitTimeInMs(200);
476     getVhal()->setGetValueResults({
477             GetValueResult{
478                     .requestId = 0,
479                     .status = StatusCode::OK,
480                     .prop =
481                             VehiclePropValue{
482                                     .prop = TEST_PROP_ID,
483                                     .areaId = TEST_AREA_ID,
484                                     .value =
485                                             RawPropValues{
486                                                     .int32Values = {1},
487                                             },
488                             },
489             },
490     });
491 
492     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
493     std::mutex lock;
494     std::condition_variable cv;
495     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
496     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
497     bool gotResult = false;
498     bool* gotResultPtr = &gotResult;
499 
500     auto callback = std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
501             [&lock, &cv, resultPtr,
502              gotResultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
503                 {
504                     std::lock_guard<std::mutex> lockGuard(lock);
505                     *resultPtr = std::move(r);
506                     *gotResultPtr = true;
507                 }
508                 cv.notify_one();
509             });
510     getClient()->getValue(propValue, callback);
511 
512     std::unique_lock<std::mutex> lk(lock);
513     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
514 
515     ASSERT_TRUE(gotResult);
516     ASSERT_EQ(getVhal()->getGetValueRequests(),
517               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
518     ASSERT_FALSE(result.ok());
519     ASSERT_EQ(result.error().code(), ErrorCode::TIMEOUT);
520 }
521 
TEST_F(AidlVhalClientTest,testGetValueErrorStatus)522 TEST_F(AidlVhalClientTest, testGetValueErrorStatus) {
523     VehiclePropValue testProp{
524             .prop = TEST_PROP_ID,
525             .areaId = TEST_AREA_ID,
526     };
527     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
528 
529     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
530     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
531     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
532 
533     getClient()->getValue(propValue,
534                           std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
535                                   [resultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
536                                       *resultPtr = std::move(r);
537                                   }));
538 
539     ASSERT_EQ(getVhal()->getGetValueRequests(),
540               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
541     ASSERT_FALSE(result.ok());
542     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
543 }
544 
TEST_F(AidlVhalClientTest,testGetValueNonOkayResult)545 TEST_F(AidlVhalClientTest, testGetValueNonOkayResult) {
546     VehiclePropValue testProp{
547             .prop = TEST_PROP_ID,
548             .areaId = TEST_AREA_ID,
549     };
550     getVhal()->setGetValueResults({
551             GetValueResult{
552                     .requestId = 0,
553                     .status = StatusCode::INTERNAL_ERROR,
554             },
555     });
556 
557     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
558     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
559     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
560 
561     getClient()->getValue(propValue,
562                           std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
563                                   [resultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
564                                       *resultPtr = std::move(r);
565                                   }));
566 
567     ASSERT_EQ(getVhal()->getGetValueRequests(),
568               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
569     ASSERT_FALSE(result.ok());
570     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
571 }
572 
TEST_F(AidlVhalClientTest,testGetValueIgnoreInvalidRequestId)573 TEST_F(AidlVhalClientTest, testGetValueIgnoreInvalidRequestId) {
574     VehiclePropValue testProp{
575             .prop = TEST_PROP_ID,
576             .areaId = TEST_AREA_ID,
577     };
578     getVhal()->setGetValueResults({
579             GetValueResult{
580                     .requestId = 0,
581                     .status = StatusCode::OK,
582                     .prop =
583                             VehiclePropValue{
584                                     .prop = TEST_PROP_ID,
585                                     .areaId = TEST_AREA_ID,
586                                     .value =
587                                             RawPropValues{
588                                                     .int32Values = {1},
589                                             },
590                             },
591             },
592             // This result has invalid request ID and should be ignored.
593             GetValueResult{
594                     .requestId = 1,
595                     .status = StatusCode::INTERNAL_ERROR,
596             },
597     });
598 
599     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
600     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
601     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
602 
603     getClient()->getValue(propValue,
604                           std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
605                                   [resultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
606                                       *resultPtr = std::move(r);
607                                   }));
608 
609     ASSERT_EQ(getVhal()->getGetValueRequests(),
610               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
611     ASSERT_TRUE(result.ok());
612     auto gotValue = std::move(result.value());
613     ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
614     ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
615     ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
616 }
617 
TEST_F(AidlVhalClientTest,testSetValueNormal)618 TEST_F(AidlVhalClientTest, testSetValueNormal) {
619     VehiclePropValue testProp{
620             .prop = TEST_PROP_ID,
621             .areaId = TEST_AREA_ID,
622     };
623     getVhal()->setWaitTimeInMs(10);
624     getVhal()->setSetValueResults({
625             SetValueResult{
626                     .requestId = 0,
627                     .status = StatusCode::OK,
628             },
629     });
630 
631     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
632     std::mutex lock;
633     std::condition_variable cv;
634     VhalClientResult<void> result;
635     VhalClientResult<void>* resultPtr = &result;
636     bool gotResult = false;
637     bool* gotResultPtr = &gotResult;
638 
639     auto callback = std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
640             [&lock, &cv, resultPtr, gotResultPtr](VhalClientResult<void> r) {
641                 {
642                     std::lock_guard<std::mutex> lockGuard(lock);
643                     *resultPtr = std::move(r);
644                     *gotResultPtr = true;
645                 }
646                 cv.notify_one();
647             });
648     getClient()->setValue(propValue, callback);
649 
650     std::unique_lock<std::mutex> lk(lock);
651     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
652 
653     ASSERT_TRUE(gotResult);
654     ASSERT_EQ(getVhal()->getSetValueRequests(),
655               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
656     ASSERT_TRUE(result.ok());
657 }
658 
TEST_F(AidlVhalClientTest,testSetValueSync)659 TEST_F(AidlVhalClientTest, testSetValueSync) {
660     VehiclePropValue testProp{
661             .prop = TEST_PROP_ID,
662             .areaId = TEST_AREA_ID,
663     };
664     getVhal()->setWaitTimeInMs(10);
665     getVhal()->setSetValueResults({
666             SetValueResult{
667                     .requestId = 0,
668                     .status = StatusCode::OK,
669             },
670     });
671 
672     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
673     VhalClientResult<void> result = getClient()->setValueSync(propValue);
674 
675     ASSERT_EQ(getVhal()->getSetValueRequests(),
676               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
677     ASSERT_TRUE(result.ok());
678 }
679 
TEST_F(AidlVhalClientTest,testSetValueTimeout)680 TEST_F(AidlVhalClientTest, testSetValueTimeout) {
681     VehiclePropValue testProp{
682             .prop = TEST_PROP_ID,
683             .areaId = TEST_AREA_ID,
684     };
685     // The request will time-out before the response.
686     getVhal()->setWaitTimeInMs(200);
687     getVhal()->setSetValueResults({
688             SetValueResult{
689                     .requestId = 0,
690                     .status = StatusCode::OK,
691             },
692     });
693 
694     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
695     std::mutex lock;
696     std::condition_variable cv;
697     VhalClientResult<void> result;
698     VhalClientResult<void>* resultPtr = &result;
699     bool gotResult = false;
700     bool* gotResultPtr = &gotResult;
701 
702     auto callback = std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
703             [&lock, &cv, resultPtr, gotResultPtr](VhalClientResult<void> r) {
704                 {
705                     std::lock_guard<std::mutex> lockGuard(lock);
706                     *resultPtr = std::move(r);
707                     *gotResultPtr = true;
708                 }
709                 cv.notify_one();
710             });
711     getClient()->setValue(propValue, callback);
712 
713     std::unique_lock<std::mutex> lk(lock);
714     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
715 
716     ASSERT_TRUE(gotResult);
717     ASSERT_EQ(getVhal()->getSetValueRequests(),
718               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
719     ASSERT_FALSE(result.ok());
720     ASSERT_EQ(result.error().code(), ErrorCode::TIMEOUT);
721 }
722 
TEST_F(AidlVhalClientTest,testSetValueErrorStatus)723 TEST_F(AidlVhalClientTest, testSetValueErrorStatus) {
724     VehiclePropValue testProp{
725             .prop = TEST_PROP_ID,
726             .areaId = TEST_AREA_ID,
727     };
728     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
729 
730     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
731     VhalClientResult<void> result;
732     VhalClientResult<void>* resultPtr = &result;
733 
734     getClient()->setValue(propValue,
735                           std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
736                                   [resultPtr](VhalClientResult<void> r) {
737                                       *resultPtr = std::move(r);
738                                   }));
739 
740     ASSERT_EQ(getVhal()->getSetValueRequests(),
741               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
742     ASSERT_FALSE(result.ok());
743     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
744 }
745 
TEST_F(AidlVhalClientTest,testSetValueNonOkayResult)746 TEST_F(AidlVhalClientTest, testSetValueNonOkayResult) {
747     VehiclePropValue testProp{
748             .prop = TEST_PROP_ID,
749             .areaId = TEST_AREA_ID,
750     };
751     getVhal()->setSetValueResults({
752             SetValueResult{
753                     .requestId = 0,
754                     .status = StatusCode::INTERNAL_ERROR,
755             },
756     });
757 
758     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
759     VhalClientResult<void> result;
760     VhalClientResult<void>* resultPtr = &result;
761 
762     getClient()->setValue(propValue,
763                           std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
764                                   [resultPtr](VhalClientResult<void> r) {
765                                       *resultPtr = std::move(r);
766                                   }));
767 
768     ASSERT_EQ(getVhal()->getSetValueRequests(),
769               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
770     ASSERT_FALSE(result.ok());
771     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
772 }
773 
TEST_F(AidlVhalClientTest,testSetValueIgnoreInvalidRequestId)774 TEST_F(AidlVhalClientTest, testSetValueIgnoreInvalidRequestId) {
775     VehiclePropValue testProp{
776             .prop = TEST_PROP_ID,
777             .areaId = TEST_AREA_ID,
778     };
779     getVhal()->setSetValueResults({
780             SetValueResult{
781                     .requestId = 0,
782                     .status = StatusCode::OK,
783             },
784             // This result has invalid request ID and should be ignored.
785             SetValueResult{
786                     .requestId = 1,
787                     .status = StatusCode::INTERNAL_ERROR,
788             },
789     });
790 
791     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
792     VhalClientResult<void> result;
793     VhalClientResult<void>* resultPtr = &result;
794 
795     getClient()->setValue(propValue,
796                           std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
797                                   [resultPtr](VhalClientResult<void> r) {
798                                       *resultPtr = std::move(r);
799                                   }));
800 
801     ASSERT_EQ(getVhal()->getSetValueRequests(),
802               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
803     ASSERT_TRUE(result.ok());
804 }
805 
TEST_F(AidlVhalClientTest,testAddOnBinderDiedCallback)806 TEST_F(AidlVhalClientTest, testAddOnBinderDiedCallback) {
807     struct Result {
808         bool callbackOneCalled = false;
809         bool callbackTwoCalled = false;
810     } result;
811 
812     getClient()->addOnBinderDiedCallback(std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
813             [&result] { result.callbackOneCalled = true; }));
814     getClient()->addOnBinderDiedCallback(std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
815             [&result] { result.callbackTwoCalled = true; }));
816     triggerBinderDied();
817 
818     ASSERT_TRUE(result.callbackOneCalled);
819     ASSERT_TRUE(result.callbackTwoCalled);
820 
821     ASSERT_EQ(countOnBinderDiedCallbacks(), static_cast<size_t>(0));
822 }
823 
TEST_F(AidlVhalClientTest,testOnBinderDied_noDeadLock)824 TEST_F(AidlVhalClientTest, testOnBinderDied_noDeadLock) {
825     getClient()->addOnBinderDiedCallback(
826             std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>([this] {
827                 // This will trigger the destructor for AidlVhalClient. This must not cause dead
828                 // lock.
829                 resetClient();
830             }));
831 
832     triggerBinderDied();
833 }
834 
TEST_F(AidlVhalClientTest,testRemoveOnBinderDiedCallback)835 TEST_F(AidlVhalClientTest, testRemoveOnBinderDiedCallback) {
836     struct Result {
837         bool callbackOneCalled = false;
838         bool callbackTwoCalled = false;
839     } result;
840 
841     auto callbackOne = std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
842             [&result] { result.callbackOneCalled = true; });
843     auto callbackTwo = std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
844             [&result] { result.callbackTwoCalled = true; });
845     getClient()->addOnBinderDiedCallback(callbackOne);
846     getClient()->addOnBinderDiedCallback(callbackTwo);
847     getClient()->removeOnBinderDiedCallback(callbackOne);
848     triggerBinderDied();
849 
850     ASSERT_FALSE(result.callbackOneCalled);
851     ASSERT_TRUE(result.callbackTwoCalled);
852     ASSERT_EQ(countOnBinderDiedCallbacks(), static_cast<size_t>(0));
853 }
854 
TEST_F(AidlVhalClientTest,testGetAllPropConfigs)855 TEST_F(AidlVhalClientTest, testGetAllPropConfigs) {
856     getVhal()->setPropConfigs({
857             VehiclePropConfig{
858                     .prop = TEST_PROP_ID,
859                     .access = TEST_GLOBAL_ACCESS,
860                     .areaConfigs = {{
861                                             .areaId = TEST_AREA_ID,
862                                             .minInt32Value = 0,
863                                             .maxInt32Value = 1,
864                                             .supportVariableUpdateRate = true,
865                                     },
866                                     {
867                                             .areaId = TEST_AREA_ID_2,
868                                             .access = TEST_AREA_ACCESS,
869                                             .minInt32Value = 2,
870                                             .maxInt32Value = 3,
871                                     }},
872             },
873             VehiclePropConfig{
874                     .prop = TEST_PROP_ID_2,
875             },
876     });
877 
878     auto result = getClient()->getAllPropConfigs();
879 
880     ASSERT_TRUE(result.ok());
881     std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
882 
883     ASSERT_EQ(configs.size(), static_cast<size_t>(2));
884     ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
885     ASSERT_EQ(configs[0]->getAccess(), toInt(TEST_GLOBAL_ACCESS));
886     ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(2));
887 
888     const std::unique_ptr<IHalAreaConfig>& areaConfig0 = configs[0]->getAreaConfigs()[0];
889     ASSERT_EQ(areaConfig0->getAreaId(), TEST_AREA_ID);
890     ASSERT_EQ(areaConfig0->getAccess(), toInt(TEST_GLOBAL_ACCESS));
891     ASSERT_EQ(areaConfig0->getMinInt32Value(), 0);
892     ASSERT_EQ(areaConfig0->getMaxInt32Value(), 1);
893     ASSERT_TRUE(areaConfig0->isVariableUpdateRateSupported());
894 
895     const std::unique_ptr<IHalAreaConfig>& areaConfig1 = configs[0]->getAreaConfigs()[1];
896     ASSERT_EQ(areaConfig1->getAreaId(), TEST_AREA_ID_2);
897     ASSERT_EQ(areaConfig1->getAccess(), toInt(TEST_AREA_ACCESS));
898     ASSERT_EQ(areaConfig1->getMinInt32Value(), 2);
899     ASSERT_EQ(areaConfig1->getMaxInt32Value(), 3);
900     ASSERT_FALSE(areaConfig1->isVariableUpdateRateSupported());
901 
902     ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
903     ASSERT_EQ(configs[1]->getAccess(), 0);
904     ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(1));
905 
906     const std::unique_ptr<IHalAreaConfig>& areaConfig2 = configs[1]->getAreaConfigs()[0];
907     ASSERT_EQ(areaConfig2->getAreaId(), 0);
908     ASSERT_EQ(areaConfig2->getAccess(), 0);
909     ASSERT_FALSE(areaConfig2->isVariableUpdateRateSupported());
910 }
911 
TEST_F(AidlVhalClientTest,testGetAllPropConfigsError)912 TEST_F(AidlVhalClientTest, testGetAllPropConfigsError) {
913     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
914 
915     auto result = getClient()->getAllPropConfigs();
916 
917     ASSERT_FALSE(result.ok());
918     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
919 }
920 
TEST_F(AidlVhalClientTest,testGetPropConfigs)921 TEST_F(AidlVhalClientTest, testGetPropConfigs) {
922     getVhal()->setPropConfigs({
923             VehiclePropConfig{
924                     .prop = TEST_PROP_ID,
925                     .access = TEST_GLOBAL_ACCESS,
926                     .areaConfigs = {{
927                                             .areaId = TEST_AREA_ID,
928                                             .minInt32Value = 0,
929                                             .maxInt32Value = 1,
930                                             .supportVariableUpdateRate = true,
931                                     },
932                                     {
933                                             .areaId = TEST_AREA_ID_2,
934                                             .access = TEST_AREA_ACCESS,
935                                             .minInt32Value = 2,
936                                             .maxInt32Value = 3,
937                                     }},
938             },
939             VehiclePropConfig{
940                     .prop = TEST_PROP_ID_2,
941             },
942     });
943 
944     std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
945     auto result = getClient()->getPropConfigs(propIds);
946 
947     ASSERT_EQ(getVhal()->getGetPropConfigPropIds(), propIds);
948     ASSERT_TRUE(result.ok());
949     std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
950 
951     ASSERT_EQ(configs.size(), static_cast<size_t>(2));
952     ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
953     ASSERT_EQ(configs[0]->getAccess(), toInt(TEST_GLOBAL_ACCESS));
954     ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(2));
955 
956     const std::unique_ptr<IHalAreaConfig>& areaConfig0 = configs[0]->getAreaConfigs()[0];
957     ASSERT_EQ(areaConfig0->getAreaId(), TEST_AREA_ID);
958     ASSERT_EQ(areaConfig0->getAccess(), toInt(TEST_GLOBAL_ACCESS));
959     ASSERT_EQ(areaConfig0->getMinInt32Value(), 0);
960     ASSERT_EQ(areaConfig0->getMaxInt32Value(), 1);
961     ASSERT_TRUE(areaConfig0->isVariableUpdateRateSupported());
962 
963     const std::unique_ptr<IHalAreaConfig>& areaConfig1 = configs[0]->getAreaConfigs()[1];
964     ASSERT_EQ(areaConfig1->getAreaId(), TEST_AREA_ID_2);
965     ASSERT_EQ(areaConfig1->getAccess(), toInt(TEST_AREA_ACCESS));
966     ASSERT_EQ(areaConfig1->getMinInt32Value(), 2);
967     ASSERT_EQ(areaConfig1->getMaxInt32Value(), 3);
968     ASSERT_FALSE(areaConfig1->isVariableUpdateRateSupported());
969 
970     ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
971     ASSERT_EQ(configs[1]->getAccess(), 0);
972     ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(1));
973 
974     const std::unique_ptr<IHalAreaConfig>& areaConfig2 = configs[1]->getAreaConfigs()[0];
975     ASSERT_EQ(areaConfig2->getAreaId(), 0);
976     ASSERT_EQ(areaConfig2->getAccess(), 0);
977     ASSERT_FALSE(areaConfig2->isVariableUpdateRateSupported());
978 }
979 
TEST_F(AidlVhalClientTest,testGetPropConfigsError)980 TEST_F(AidlVhalClientTest, testGetPropConfigsError) {
981     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
982 
983     std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
984     auto result = getClient()->getPropConfigs(propIds);
985 
986     ASSERT_FALSE(result.ok());
987 }
988 
TEST_F(AidlVhalClientTest,testSubscribe)989 TEST_F(AidlVhalClientTest, testSubscribe) {
990     std::vector<SubscribeOptions> options = {
991             {
992                     .propId = TEST_PROP_ID,
993                     .areaIds = {TEST_AREA_ID},
994                     .sampleRate = 1.0,
995             },
996             {
997                     .propId = TEST_PROP_ID_2,
998                     .sampleRate = 2.0,
999             },
1000     };
1001 
1002     auto callback = std::make_shared<MockSubscriptionCallback>();
1003     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
1004     auto result = subscriptionClient->subscribe(options);
1005 
1006     ASSERT_TRUE(result.ok());
1007     ASSERT_EQ(getVhal()->getSubscriptionOptions(), options);
1008 
1009     getVhal()->triggerOnPropertyEvent(std::vector<VehiclePropValue>{
1010             {
1011                     .prop = TEST_PROP_ID,
1012                     .areaId = TEST_AREA_ID,
1013                     .value.int32Values = {1},
1014             },
1015     });
1016 
1017     ASSERT_EQ(callback->getEventPropIds(), std::vector<int32_t>({TEST_PROP_ID}));
1018 
1019     getVhal()->triggerSetErrorEvent(std::vector<VehiclePropError>({
1020             {
1021                     .propId = TEST_PROP_ID,
1022                     .areaId = TEST_AREA_ID,
1023                     .errorCode = StatusCode::INTERNAL_ERROR,
1024             },
1025     }));
1026 
1027     auto errors = callback->getErrors();
1028     ASSERT_EQ(errors.size(), static_cast<size_t>(1));
1029     ASSERT_EQ(errors[0].propId, TEST_PROP_ID);
1030     ASSERT_EQ(errors[0].areaId, TEST_AREA_ID);
1031     ASSERT_EQ(errors[0].status, StatusCode::INTERNAL_ERROR);
1032 }
1033 
TEST_F(AidlVhalClientTest,testSubscribeError)1034 TEST_F(AidlVhalClientTest, testSubscribeError) {
1035     std::vector<SubscribeOptions> options = {
1036             {
1037                     .propId = TEST_PROP_ID,
1038                     .areaIds = {TEST_AREA_ID},
1039                     .sampleRate = 1.0,
1040             },
1041             {
1042                     .propId = TEST_PROP_ID_2,
1043                     .sampleRate = 2.0,
1044             },
1045     };
1046 
1047     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
1048     auto callback = std::make_shared<MockSubscriptionCallback>();
1049     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
1050     auto result = subscriptionClient->subscribe(options);
1051 
1052     ASSERT_FALSE(result.ok());
1053 }
1054 
TEST_F(AidlVhalClientTest,testUnubscribe)1055 TEST_F(AidlVhalClientTest, testUnubscribe) {
1056     auto callback = std::make_shared<MockSubscriptionCallback>();
1057     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
1058     auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
1059 
1060     ASSERT_TRUE(result.ok());
1061     ASSERT_EQ(getVhal()->getUnsubscribedPropIds(), std::vector<int32_t>({TEST_PROP_ID}));
1062 }
1063 
TEST_F(AidlVhalClientTest,testUnubscribeError)1064 TEST_F(AidlVhalClientTest, testUnubscribeError) {
1065     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
1066     auto callback = std::make_shared<MockSubscriptionCallback>();
1067     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
1068     auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
1069 
1070     ASSERT_FALSE(result.ok());
1071 }
1072 
TEST_F(AidlVhalClientTest,testGetRemoteInterfaceVersion)1073 TEST_F(AidlVhalClientTest, testGetRemoteInterfaceVersion) {
1074     // The AIDL VHAL should be v2 or higher.
1075     ASSERT_THAT(getClient()->getRemoteInterfaceVersion(), Gt(1));
1076 }
1077 
TEST_F(AidlVhalClientTest,testSubscribeOptionsBuilder)1078 TEST_F(AidlVhalClientTest, testSubscribeOptionsBuilder) {
1079     auto optionsBuilder = SubscribeOptionsBuilder(TEST_PROP_ID);
1080     optionsBuilder.setSampleRate(1.23f);
1081     optionsBuilder.addAreaId(1);
1082     optionsBuilder.addAreaId(2);
1083     optionsBuilder.setResolution(2.34f);
1084 
1085     auto options = optionsBuilder.build();
1086 
1087     ASSERT_EQ(options,
1088               (SubscribeOptions{
1089                       .propId = TEST_PROP_ID,
1090                       .areaIds = {1, 2},
1091                       .sampleRate = 1.23f,
1092                       .resolution = 2.34f,
1093                       // VUR is true by default
1094                       .enableVariableUpdateRate = true,
1095               }));
1096 }
1097 
TEST_F(AidlVhalClientTest,testSubscribeOptionsBuilder_disableVur)1098 TEST_F(AidlVhalClientTest, testSubscribeOptionsBuilder_disableVur) {
1099     auto optionsBuilder = SubscribeOptionsBuilder(TEST_PROP_ID);
1100     optionsBuilder.setSampleRate(1.23f);
1101     optionsBuilder.addAreaId(1);
1102     optionsBuilder.addAreaId(2);
1103     optionsBuilder.setResolution(2.34f);
1104     optionsBuilder.setEnableVariableUpdateRate(false);
1105 
1106     auto options = optionsBuilder.build();
1107 
1108     ASSERT_EQ(options,
1109               (SubscribeOptions{
1110                       .propId = TEST_PROP_ID,
1111                       .areaIds = {1, 2},
1112                       .sampleRate = 1.23f,
1113                       .resolution = 2.34f,
1114                       .enableVariableUpdateRate = false,
1115               }));
1116 }
1117 
TEST_F(AidlVhalClientTest,testAidlHalPropValueClone_valueIsTheSame)1118 TEST_F(AidlVhalClientTest, testAidlHalPropValueClone_valueIsTheSame) {
1119     VehiclePropValue testProp{.prop = TEST_PROP_ID,
1120                               .areaId = TEST_AREA_ID,
1121                               .value = {
1122                                       .int32Values = {1, 2},
1123                                       .floatValues = {1.1, 2.2},
1124                               }};
1125     auto testPropCopy = testProp;
1126     std::unique_ptr<IHalPropValue> halPropValue =
1127             std::make_unique<AidlHalPropValue>(std::move(testPropCopy));
1128     auto halPropValueClone = halPropValue->clone();
1129 
1130     EXPECT_EQ(halPropValueClone->getPropId(), TEST_PROP_ID);
1131     EXPECT_EQ(halPropValueClone->getAreaId(), TEST_AREA_ID);
1132     EXPECT_EQ(halPropValueClone->getInt32Values(), std::vector<int32_t>({1, 2}));
1133     EXPECT_EQ(halPropValueClone->getFloatValues(), std::vector<float>({1.1, 2.2}));
1134 }
1135 
TEST_F(AidlVhalClientTest,testAidlHalPropValueClone_modifyCloneDoesNotAffectOrig)1136 TEST_F(AidlVhalClientTest, testAidlHalPropValueClone_modifyCloneDoesNotAffectOrig) {
1137     std::vector<int32_t> int32Values1 = {1, 2};
1138     std::vector<float> floatValues1 = {1.1, 2.2};
1139     std::vector<int32_t> int32Values2 = {5, 4, 3, 2, 1};
1140     std::vector<float> floatValues2 = {3.3, 2.2, 1.1};
1141 
1142     VehiclePropValue testProp{.prop = TEST_PROP_ID,
1143                               .areaId = TEST_AREA_ID,
1144                               .value = {
1145                                       .int32Values = int32Values1,
1146                                       .floatValues = floatValues1,
1147                               }};
1148     auto testPropCopy = testProp;
1149     std::unique_ptr<IHalPropValue> halPropValue =
1150             std::make_unique<AidlHalPropValue>(std::move(testPropCopy));
1151     auto halPropValueClone = halPropValue->clone();
1152 
1153     halPropValueClone->setInt32Values(int32Values2);
1154     halPropValueClone->setFloatValues(floatValues2);
1155 
1156     EXPECT_EQ(halPropValue->getInt32Values(), int32Values1);
1157     EXPECT_EQ(halPropValue->getFloatValues(), floatValues1);
1158     EXPECT_EQ(halPropValueClone->getInt32Values(), int32Values2);
1159     EXPECT_EQ(halPropValueClone->getFloatValues(), floatValues2);
1160 }
1161 
1162 }  // namespace aidl_test
1163 }  // namespace vhal
1164 }  // namespace automotive
1165 }  // namespace frameworks
1166 }  // namespace android
1167