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