• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <aidl/android/hardware/automotive/vehicle/BnVehicle.h>
18 #include <android/binder_ibinder.h>
19 #include <gtest/gtest.h>
20 
21 #include <AidlHalPropValue.h>
22 #include <AidlVhalClient.h>
23 #include <VehicleHalTypes.h>
24 #include <VehicleUtils.h>
25 
26 #include <atomic>
27 #include <condition_variable>  // NOLINT
28 #include <mutex>               // NOLINT
29 #include <thread>              // NOLINT
30 
31 namespace android {
32 namespace frameworks {
33 namespace automotive {
34 namespace vhal {
35 namespace aidl_test {
36 
37 using ::android::hardware::automotive::vehicle::toInt;
38 
39 using ::aidl::android::hardware::automotive::vehicle::BnVehicle;
40 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
41 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
42 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
43 using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
44 using ::aidl::android::hardware::automotive::vehicle::IVehicle;
45 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
46 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
47 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
48 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
49 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
50 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
51 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
52 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
53 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
54 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
55 using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
56 using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
57 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
58 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
59 
60 using ::ndk::ScopedAStatus;
61 using ::ndk::SharedRefBase;
62 
63 class MockVhal final : public BnVehicle {
64 public:
65     using CallbackType = std::shared_ptr<IVehicleCallback>;
66 
~MockVhal()67     ~MockVhal() {
68         std::unique_lock<std::mutex> lk(mLock);
69         mCv.wait_for(lk, std::chrono::milliseconds(1000), [this] { return mThreadCount == 0; });
70     }
71 
getAllPropConfigs(VehiclePropConfigs * returnConfigs)72     ScopedAStatus getAllPropConfigs(VehiclePropConfigs* returnConfigs) override {
73         if (mStatus != StatusCode::OK) {
74             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
75         }
76 
77         returnConfigs->payloads = mPropConfigs;
78         return ScopedAStatus::ok();
79     }
80 
getValues(const CallbackType & callback,const GetValueRequests & requests)81     ScopedAStatus getValues(const CallbackType& callback,
82                             const GetValueRequests& requests) override {
83         mGetValueRequests = requests.payloads;
84 
85         if (mStatus != StatusCode::OK) {
86             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
87         }
88 
89         if (mWaitTimeInMs == 0) {
90             callback->onGetValues(GetValueResults{.payloads = mGetValueResults});
91         } else {
92             mThreadCount++;
93             std::thread t([this, callback]() {
94                 std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTimeInMs));
95                 callback->onGetValues(GetValueResults{.payloads = mGetValueResults});
96                 mThreadCount--;
97                 mCv.notify_one();
98             });
99             // Detach the thread here so we do not have to maintain the thread object. mThreadCount
100             // and mCv make sure we wait for all threads to end before we exit.
101             t.detach();
102         }
103         return ScopedAStatus::ok();
104     }
105 
setValues(const CallbackType & callback,const SetValueRequests & requests)106     ScopedAStatus setValues(const CallbackType& callback,
107                             const SetValueRequests& requests) override {
108         mSetValueRequests = requests.payloads;
109 
110         if (mStatus != StatusCode::OK) {
111             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
112         }
113 
114         if (mWaitTimeInMs == 0) {
115             callback->onSetValues(SetValueResults{.payloads = mSetValueResults});
116         } else {
117             mThreadCount++;
118             std::thread t([this, callback]() {
119                 std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTimeInMs));
120                 callback->onSetValues(SetValueResults{.payloads = mSetValueResults});
121                 mThreadCount--;
122                 mCv.notify_one();
123             });
124             // Detach the thread here so we do not have to maintain the thread object. mThreadCount
125             // and mCv make sure we wait for all threads to end before we exit.
126             t.detach();
127         }
128         return ScopedAStatus::ok();
129     }
130 
getPropConfigs(const std::vector<int32_t> & props,VehiclePropConfigs * returnConfigs)131     ScopedAStatus getPropConfigs(const std::vector<int32_t>& props,
132                                  VehiclePropConfigs* returnConfigs) override {
133         mGetPropConfigPropIds = props;
134         if (mStatus != StatusCode::OK) {
135             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
136         }
137 
138         returnConfigs->payloads = mPropConfigs;
139         return ScopedAStatus::ok();
140     }
141 
subscribe(const CallbackType & callback,const std::vector<SubscribeOptions> & options,int32_t maxSharedMemoryFileCount)142     ScopedAStatus subscribe(const CallbackType& callback,
143                             const std::vector<SubscribeOptions>& options,
144                             [[maybe_unused]] int32_t maxSharedMemoryFileCount) override {
145         mSubscriptionCallback = callback;
146         mSubscriptionOptions = options;
147 
148         if (mStatus != StatusCode::OK) {
149             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
150         }
151         return ScopedAStatus::ok();
152     }
153 
unsubscribe(const CallbackType & callback,const std::vector<int32_t> & propIds)154     ScopedAStatus unsubscribe([[maybe_unused]] const CallbackType& callback,
155                               const std::vector<int32_t>& propIds) override {
156         mUnsubscribePropIds = propIds;
157 
158         if (mStatus != StatusCode::OK) {
159             return ScopedAStatus::fromServiceSpecificError(toInt(mStatus));
160         }
161         return ScopedAStatus::ok();
162     }
163 
returnSharedMemory(const CallbackType & callback,int64_t sharedMemoryId)164     ScopedAStatus returnSharedMemory([[maybe_unused]] const CallbackType& callback,
165                                      [[maybe_unused]] int64_t sharedMemoryId) override {
166         return ScopedAStatus::ok();
167     }
168 
169     // Test Functions
170 
setGetValueResults(std::vector<GetValueResult> results)171     void setGetValueResults(std::vector<GetValueResult> results) { mGetValueResults = results; }
172 
getGetValueRequests()173     std::vector<GetValueRequest> getGetValueRequests() { return mGetValueRequests; }
174 
setSetValueResults(std::vector<SetValueResult> results)175     void setSetValueResults(std::vector<SetValueResult> results) { mSetValueResults = results; }
176 
getSetValueRequests()177     std::vector<SetValueRequest> getSetValueRequests() { return mSetValueRequests; }
178 
setWaitTimeInMs(int64_t waitTimeInMs)179     void setWaitTimeInMs(int64_t waitTimeInMs) { mWaitTimeInMs = waitTimeInMs; }
180 
setStatus(StatusCode status)181     void setStatus(StatusCode status) { mStatus = status; }
182 
setPropConfigs(std::vector<VehiclePropConfig> configs)183     void setPropConfigs(std::vector<VehiclePropConfig> configs) { mPropConfigs = configs; }
184 
getGetPropConfigPropIds()185     std::vector<int32_t> getGetPropConfigPropIds() { return mGetPropConfigPropIds; }
186 
getSubscriptionOptions()187     std::vector<SubscribeOptions> getSubscriptionOptions() { return mSubscriptionOptions; }
188 
triggerOnPropertyEvent(const std::vector<VehiclePropValue> & values)189     void triggerOnPropertyEvent(const std::vector<VehiclePropValue>& values) {
190         VehiclePropValues propValues = {
191                 .payloads = values,
192         };
193         mSubscriptionCallback->onPropertyEvent(propValues, /*sharedMemoryCount=*/0);
194     }
195 
triggerSetErrorEvent(const std::vector<VehiclePropError> & errors)196     void triggerSetErrorEvent(const std::vector<VehiclePropError>& errors) {
197         VehiclePropErrors propErrors = {
198                 .payloads = errors,
199         };
200         mSubscriptionCallback->onPropertySetError(propErrors);
201     }
202 
getUnsubscribedPropIds()203     std::vector<int32_t> getUnsubscribedPropIds() { return mUnsubscribePropIds; }
204 
205 private:
206     std::mutex mLock;
207     std::vector<GetValueResult> mGetValueResults;
208     std::vector<GetValueRequest> mGetValueRequests;
209     std::vector<SetValueResult> mSetValueResults;
210     std::vector<SetValueRequest> mSetValueRequests;
211     std::vector<VehiclePropConfig> mPropConfigs;
212     std::vector<int32_t> mGetPropConfigPropIds;
213     int64_t mWaitTimeInMs = 0;
214     StatusCode mStatus = StatusCode::OK;
215     std::condition_variable mCv;
216     std::atomic<int> mThreadCount = 0;
217     CallbackType mSubscriptionCallback;
218     std::vector<SubscribeOptions> mSubscriptionOptions;
219     std::vector<int32_t> mUnsubscribePropIds;
220 };
221 
222 class MockSubscriptionCallback : public ISubscriptionCallback {
223 public:
onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>> & values)224     void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) override {
225         for (const auto& value : values) {
226             mEventPropIds.push_back(value->getPropId());
227         }
228     }
onPropertySetError(const std::vector<HalPropError> & errors)229     void onPropertySetError(const std::vector<HalPropError>& errors) override { mErrors = errors; }
230 
getEventPropIds()231     std::vector<int32_t> getEventPropIds() { return mEventPropIds; }
232 
getErrors()233     std::vector<HalPropError> getErrors() { return mErrors; }
234 
235 private:
236     std::vector<int32_t> mEventPropIds;
237     std::vector<HalPropError> mErrors;
238 };
239 
240 class AidlVhalClientTest : public ::testing::Test {
241 protected:
242     class TestLinkUnlinkImpl final : public AidlVhalClient::ILinkUnlinkToDeath {
243     public:
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)244         binder_status_t linkToDeath([[maybe_unused]] AIBinder* binder,
245                                     [[maybe_unused]] AIBinder_DeathRecipient* recipient,
246                                     void* cookie) override {
247             mCookie = cookie;
248             return STATUS_OK;
249         }
250 
unlinkToDeath(AIBinder *,AIBinder_DeathRecipient *,void *)251         binder_status_t unlinkToDeath(AIBinder*, AIBinder_DeathRecipient*, void*) override {
252             // DO nothing.
253             return STATUS_OK;
254         }
255 
getCookie()256         void* getCookie() { return mCookie; }
257 
258     private:
259         void* mCookie;
260     };
261 
262     constexpr static int32_t TEST_PROP_ID = 1;
263     constexpr static int32_t TEST_AREA_ID = 2;
264     constexpr static int32_t TEST_PROP_ID_2 = 3;
265     constexpr static int64_t TEST_TIMEOUT_IN_MS = 100;
266 
SetUp()267     void SetUp() override {
268         mVhal = SharedRefBase::make<MockVhal>();
269         auto impl = std::make_unique<TestLinkUnlinkImpl>();
270         // We are sure impl would be alive when we use mLinkUnlinkImpl.
271         mLinkUnlinkImpl = impl.get();
272         mVhalClient = std::unique_ptr<AidlVhalClient>(
273                 new AidlVhalClient(mVhal, TEST_TIMEOUT_IN_MS, std::move(impl)));
274     }
275 
getClient()276     AidlVhalClient* getClient() { return mVhalClient.get(); }
277 
getVhal()278     MockVhal* getVhal() { return mVhal.get(); }
279 
triggerBinderDied()280     void triggerBinderDied() { AidlVhalClient::onBinderDied(mLinkUnlinkImpl->getCookie()); }
281 
triggerBinderUnlinked()282     void triggerBinderUnlinked() { AidlVhalClient::onBinderUnlinked(mLinkUnlinkImpl->getCookie()); }
283 
countOnBinderDiedCallbacks()284     size_t countOnBinderDiedCallbacks() { return mVhalClient->countOnBinderDiedCallbacks(); }
285 
286 private:
287     std::shared_ptr<MockVhal> mVhal;
288     std::unique_ptr<AidlVhalClient> mVhalClient;
289     TestLinkUnlinkImpl* mLinkUnlinkImpl;
290 };
291 
TEST_F(AidlVhalClientTest,testIsAidl)292 TEST_F(AidlVhalClientTest, testIsAidl) {
293     ASSERT_TRUE(getClient()->isAidlVhal());
294 }
295 
TEST_F(AidlVhalClientTest,testGetValueNormal)296 TEST_F(AidlVhalClientTest, testGetValueNormal) {
297     VehiclePropValue testProp{
298             .prop = TEST_PROP_ID,
299             .areaId = TEST_AREA_ID,
300     };
301     getVhal()->setWaitTimeInMs(10);
302     getVhal()->setGetValueResults({
303             GetValueResult{
304                     .requestId = 0,
305                     .status = StatusCode::OK,
306                     .prop =
307                             VehiclePropValue{
308                                     .prop = TEST_PROP_ID,
309                                     .areaId = TEST_AREA_ID,
310                                     .value =
311                                             RawPropValues{
312                                                     .int32Values = {1},
313                                             },
314                             },
315             },
316     });
317 
318     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
319     std::mutex lock;
320     std::condition_variable cv;
321     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
322     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
323     bool gotResult = false;
324     bool* gotResultPtr = &gotResult;
325 
326     auto callback = std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
327             [&lock, &cv, resultPtr,
328              gotResultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
329                 {
330                     std::lock_guard<std::mutex> lockGuard(lock);
331                     *resultPtr = std::move(r);
332                     *gotResultPtr = true;
333                 }
334                 cv.notify_one();
335             });
336     getClient()->getValue(propValue, callback);
337 
338     std::unique_lock<std::mutex> lk(lock);
339     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
340 
341     ASSERT_TRUE(gotResult);
342     ASSERT_EQ(getVhal()->getGetValueRequests(),
343               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
344     ASSERT_TRUE(result.ok());
345     auto gotValue = std::move(result.value());
346     ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
347     ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
348     ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
349 }
350 
TEST_F(AidlVhalClientTest,testGetValueSync)351 TEST_F(AidlVhalClientTest, testGetValueSync) {
352     VehiclePropValue testProp{
353             .prop = TEST_PROP_ID,
354             .areaId = TEST_AREA_ID,
355     };
356     getVhal()->setWaitTimeInMs(10);
357     getVhal()->setGetValueResults({
358             GetValueResult{
359                     .requestId = 0,
360                     .status = StatusCode::OK,
361                     .prop =
362                             VehiclePropValue{
363                                     .prop = TEST_PROP_ID,
364                                     .areaId = TEST_AREA_ID,
365                                     .value =
366                                             RawPropValues{
367                                                     .int32Values = {1},
368                                             },
369                             },
370             },
371     });
372 
373     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
374     VhalClientResult<std::unique_ptr<IHalPropValue>> result = getClient()->getValueSync(propValue);
375 
376     ASSERT_EQ(getVhal()->getGetValueRequests(),
377               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
378     ASSERT_TRUE(result.ok());
379     auto gotValue = std::move(result.value());
380     ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
381     ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
382     ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
383 }
384 
TEST_F(AidlVhalClientTest,testGetValueTimeout)385 TEST_F(AidlVhalClientTest, testGetValueTimeout) {
386     VehiclePropValue testProp{
387             .prop = TEST_PROP_ID,
388             .areaId = TEST_AREA_ID,
389     };
390     // The request will time-out before the response.
391     getVhal()->setWaitTimeInMs(200);
392     getVhal()->setGetValueResults({
393             GetValueResult{
394                     .requestId = 0,
395                     .status = StatusCode::OK,
396                     .prop =
397                             VehiclePropValue{
398                                     .prop = TEST_PROP_ID,
399                                     .areaId = TEST_AREA_ID,
400                                     .value =
401                                             RawPropValues{
402                                                     .int32Values = {1},
403                                             },
404                             },
405             },
406     });
407 
408     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
409     std::mutex lock;
410     std::condition_variable cv;
411     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
412     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
413     bool gotResult = false;
414     bool* gotResultPtr = &gotResult;
415 
416     auto callback = std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
417             [&lock, &cv, resultPtr,
418              gotResultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
419                 {
420                     std::lock_guard<std::mutex> lockGuard(lock);
421                     *resultPtr = std::move(r);
422                     *gotResultPtr = true;
423                 }
424                 cv.notify_one();
425             });
426     getClient()->getValue(propValue, callback);
427 
428     std::unique_lock<std::mutex> lk(lock);
429     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
430 
431     ASSERT_TRUE(gotResult);
432     ASSERT_EQ(getVhal()->getGetValueRequests(),
433               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
434     ASSERT_FALSE(result.ok());
435     ASSERT_EQ(result.error().code(), ErrorCode::TIMEOUT);
436 }
437 
TEST_F(AidlVhalClientTest,testGetValueErrorStatus)438 TEST_F(AidlVhalClientTest, testGetValueErrorStatus) {
439     VehiclePropValue testProp{
440             .prop = TEST_PROP_ID,
441             .areaId = TEST_AREA_ID,
442     };
443     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
444 
445     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
446     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
447     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
448 
449     getClient()->getValue(propValue,
450                           std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
451                                   [resultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
452                                       *resultPtr = std::move(r);
453                                   }));
454 
455     ASSERT_EQ(getVhal()->getGetValueRequests(),
456               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
457     ASSERT_FALSE(result.ok());
458     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
459 }
460 
TEST_F(AidlVhalClientTest,testGetValueNonOkayResult)461 TEST_F(AidlVhalClientTest, testGetValueNonOkayResult) {
462     VehiclePropValue testProp{
463             .prop = TEST_PROP_ID,
464             .areaId = TEST_AREA_ID,
465     };
466     getVhal()->setGetValueResults({
467             GetValueResult{
468                     .requestId = 0,
469                     .status = StatusCode::INTERNAL_ERROR,
470             },
471     });
472 
473     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
474     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
475     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
476 
477     getClient()->getValue(propValue,
478                           std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
479                                   [resultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
480                                       *resultPtr = std::move(r);
481                                   }));
482 
483     ASSERT_EQ(getVhal()->getGetValueRequests(),
484               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
485     ASSERT_FALSE(result.ok());
486     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
487 }
488 
TEST_F(AidlVhalClientTest,testGetValueIgnoreInvalidRequestId)489 TEST_F(AidlVhalClientTest, testGetValueIgnoreInvalidRequestId) {
490     VehiclePropValue testProp{
491             .prop = TEST_PROP_ID,
492             .areaId = TEST_AREA_ID,
493     };
494     getVhal()->setGetValueResults({
495             GetValueResult{
496                     .requestId = 0,
497                     .status = StatusCode::OK,
498                     .prop =
499                             VehiclePropValue{
500                                     .prop = TEST_PROP_ID,
501                                     .areaId = TEST_AREA_ID,
502                                     .value =
503                                             RawPropValues{
504                                                     .int32Values = {1},
505                                             },
506                             },
507             },
508             // This result has invalid request ID and should be ignored.
509             GetValueResult{
510                     .requestId = 1,
511                     .status = StatusCode::INTERNAL_ERROR,
512             },
513     });
514 
515     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
516     VhalClientResult<std::unique_ptr<IHalPropValue>> result;
517     VhalClientResult<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
518 
519     getClient()->getValue(propValue,
520                           std::make_shared<AidlVhalClient::GetValueCallbackFunc>(
521                                   [resultPtr](VhalClientResult<std::unique_ptr<IHalPropValue>> r) {
522                                       *resultPtr = std::move(r);
523                                   }));
524 
525     ASSERT_EQ(getVhal()->getGetValueRequests(),
526               std::vector<GetValueRequest>({GetValueRequest{.requestId = 0, .prop = testProp}}));
527     ASSERT_TRUE(result.ok());
528     auto gotValue = std::move(result.value());
529     ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
530     ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
531     ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
532 }
533 
TEST_F(AidlVhalClientTest,testSetValueNormal)534 TEST_F(AidlVhalClientTest, testSetValueNormal) {
535     VehiclePropValue testProp{
536             .prop = TEST_PROP_ID,
537             .areaId = TEST_AREA_ID,
538     };
539     getVhal()->setWaitTimeInMs(10);
540     getVhal()->setSetValueResults({
541             SetValueResult{
542                     .requestId = 0,
543                     .status = StatusCode::OK,
544             },
545     });
546 
547     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
548     std::mutex lock;
549     std::condition_variable cv;
550     VhalClientResult<void> result;
551     VhalClientResult<void>* resultPtr = &result;
552     bool gotResult = false;
553     bool* gotResultPtr = &gotResult;
554 
555     auto callback = std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
556             [&lock, &cv, resultPtr, gotResultPtr](VhalClientResult<void> r) {
557                 {
558                     std::lock_guard<std::mutex> lockGuard(lock);
559                     *resultPtr = std::move(r);
560                     *gotResultPtr = true;
561                 }
562                 cv.notify_one();
563             });
564     getClient()->setValue(propValue, callback);
565 
566     std::unique_lock<std::mutex> lk(lock);
567     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
568 
569     ASSERT_TRUE(gotResult);
570     ASSERT_EQ(getVhal()->getSetValueRequests(),
571               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
572     ASSERT_TRUE(result.ok());
573 }
574 
TEST_F(AidlVhalClientTest,testSetValueSync)575 TEST_F(AidlVhalClientTest, testSetValueSync) {
576     VehiclePropValue testProp{
577             .prop = TEST_PROP_ID,
578             .areaId = TEST_AREA_ID,
579     };
580     getVhal()->setWaitTimeInMs(10);
581     getVhal()->setSetValueResults({
582             SetValueResult{
583                     .requestId = 0,
584                     .status = StatusCode::OK,
585             },
586     });
587 
588     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
589     VhalClientResult<void> result = getClient()->setValueSync(propValue);
590 
591     ASSERT_EQ(getVhal()->getSetValueRequests(),
592               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
593     ASSERT_TRUE(result.ok());
594 }
595 
TEST_F(AidlVhalClientTest,testSetValueTimeout)596 TEST_F(AidlVhalClientTest, testSetValueTimeout) {
597     VehiclePropValue testProp{
598             .prop = TEST_PROP_ID,
599             .areaId = TEST_AREA_ID,
600     };
601     // The request will time-out before the response.
602     getVhal()->setWaitTimeInMs(200);
603     getVhal()->setSetValueResults({
604             SetValueResult{
605                     .requestId = 0,
606                     .status = StatusCode::OK,
607             },
608     });
609 
610     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
611     std::mutex lock;
612     std::condition_variable cv;
613     VhalClientResult<void> result;
614     VhalClientResult<void>* resultPtr = &result;
615     bool gotResult = false;
616     bool* gotResultPtr = &gotResult;
617 
618     auto callback = std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
619             [&lock, &cv, resultPtr, gotResultPtr](VhalClientResult<void> r) {
620                 {
621                     std::lock_guard<std::mutex> lockGuard(lock);
622                     *resultPtr = std::move(r);
623                     *gotResultPtr = true;
624                 }
625                 cv.notify_one();
626             });
627     getClient()->setValue(propValue, callback);
628 
629     std::unique_lock<std::mutex> lk(lock);
630     cv.wait_for(lk, std::chrono::milliseconds(1000), [&gotResult] { return gotResult; });
631 
632     ASSERT_TRUE(gotResult);
633     ASSERT_EQ(getVhal()->getSetValueRequests(),
634               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
635     ASSERT_FALSE(result.ok());
636     ASSERT_EQ(result.error().code(), ErrorCode::TIMEOUT);
637 }
638 
TEST_F(AidlVhalClientTest,testSetValueErrorStatus)639 TEST_F(AidlVhalClientTest, testSetValueErrorStatus) {
640     VehiclePropValue testProp{
641             .prop = TEST_PROP_ID,
642             .areaId = TEST_AREA_ID,
643     };
644     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
645 
646     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
647     VhalClientResult<void> result;
648     VhalClientResult<void>* resultPtr = &result;
649 
650     getClient()->setValue(propValue,
651                           std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
652                                   [resultPtr](VhalClientResult<void> r) {
653                                       *resultPtr = std::move(r);
654                                   }));
655 
656     ASSERT_EQ(getVhal()->getSetValueRequests(),
657               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
658     ASSERT_FALSE(result.ok());
659     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
660 }
661 
TEST_F(AidlVhalClientTest,testSetValueNonOkayResult)662 TEST_F(AidlVhalClientTest, testSetValueNonOkayResult) {
663     VehiclePropValue testProp{
664             .prop = TEST_PROP_ID,
665             .areaId = TEST_AREA_ID,
666     };
667     getVhal()->setSetValueResults({
668             SetValueResult{
669                     .requestId = 0,
670                     .status = StatusCode::INTERNAL_ERROR,
671             },
672     });
673 
674     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
675     VhalClientResult<void> result;
676     VhalClientResult<void>* resultPtr = &result;
677 
678     getClient()->setValue(propValue,
679                           std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
680                                   [resultPtr](VhalClientResult<void> r) {
681                                       *resultPtr = std::move(r);
682                                   }));
683 
684     ASSERT_EQ(getVhal()->getSetValueRequests(),
685               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
686     ASSERT_FALSE(result.ok());
687     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
688 }
689 
TEST_F(AidlVhalClientTest,testSetValueIgnoreInvalidRequestId)690 TEST_F(AidlVhalClientTest, testSetValueIgnoreInvalidRequestId) {
691     VehiclePropValue testProp{
692             .prop = TEST_PROP_ID,
693             .areaId = TEST_AREA_ID,
694     };
695     getVhal()->setSetValueResults({
696             SetValueResult{
697                     .requestId = 0,
698                     .status = StatusCode::OK,
699             },
700             // This result has invalid request ID and should be ignored.
701             SetValueResult{
702                     .requestId = 1,
703                     .status = StatusCode::INTERNAL_ERROR,
704             },
705     });
706 
707     AidlHalPropValue propValue(TEST_PROP_ID, TEST_AREA_ID);
708     VhalClientResult<void> result;
709     VhalClientResult<void>* resultPtr = &result;
710 
711     getClient()->setValue(propValue,
712                           std::make_shared<AidlVhalClient::SetValueCallbackFunc>(
713                                   [resultPtr](VhalClientResult<void> r) {
714                                       *resultPtr = std::move(r);
715                                   }));
716 
717     ASSERT_EQ(getVhal()->getSetValueRequests(),
718               std::vector<SetValueRequest>({SetValueRequest{.requestId = 0, .value = testProp}}));
719     ASSERT_TRUE(result.ok());
720 }
721 
TEST_F(AidlVhalClientTest,testAddOnBinderDiedCallback)722 TEST_F(AidlVhalClientTest, testAddOnBinderDiedCallback) {
723     struct Result {
724         bool callbackOneCalled = false;
725         bool callbackTwoCalled = false;
726     } result;
727 
728     getClient()->addOnBinderDiedCallback(std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
729             [&result] { result.callbackOneCalled = true; }));
730     getClient()->addOnBinderDiedCallback(std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
731             [&result] { result.callbackTwoCalled = true; }));
732     triggerBinderDied();
733 
734     ASSERT_TRUE(result.callbackOneCalled);
735     ASSERT_TRUE(result.callbackTwoCalled);
736 
737     triggerBinderUnlinked();
738 
739     ASSERT_EQ(countOnBinderDiedCallbacks(), static_cast<size_t>(0));
740 }
741 
TEST_F(AidlVhalClientTest,testRemoveOnBinderDiedCallback)742 TEST_F(AidlVhalClientTest, testRemoveOnBinderDiedCallback) {
743     struct Result {
744         bool callbackOneCalled = false;
745         bool callbackTwoCalled = false;
746     } result;
747 
748     auto callbackOne = std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
749             [&result] { result.callbackOneCalled = true; });
750     auto callbackTwo = std::make_shared<AidlVhalClient::OnBinderDiedCallbackFunc>(
751             [&result] { result.callbackTwoCalled = true; });
752     getClient()->addOnBinderDiedCallback(callbackOne);
753     getClient()->addOnBinderDiedCallback(callbackTwo);
754     getClient()->removeOnBinderDiedCallback(callbackOne);
755     triggerBinderDied();
756 
757     ASSERT_FALSE(result.callbackOneCalled);
758     ASSERT_TRUE(result.callbackTwoCalled);
759 
760     triggerBinderUnlinked();
761 
762     ASSERT_EQ(countOnBinderDiedCallbacks(), static_cast<size_t>(0));
763 }
764 
TEST_F(AidlVhalClientTest,testGetAllPropConfigs)765 TEST_F(AidlVhalClientTest, testGetAllPropConfigs) {
766     getVhal()->setPropConfigs({
767             VehiclePropConfig{
768                     .prop = TEST_PROP_ID,
769                     .areaConfigs = {{
770                             .areaId = TEST_AREA_ID,
771                             .minInt32Value = 0,
772                             .maxInt32Value = 1,
773                     }},
774             },
775             VehiclePropConfig{
776                     .prop = TEST_PROP_ID_2,
777             },
778     });
779 
780     auto result = getClient()->getAllPropConfigs();
781 
782     ASSERT_TRUE(result.ok());
783     std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
784 
785     ASSERT_EQ(configs.size(), static_cast<size_t>(2));
786     ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
787     ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(1));
788 
789     const IHalAreaConfig* areaConfig = configs[0]->getAreaConfigs();
790     ASSERT_EQ(areaConfig->getAreaId(), TEST_AREA_ID);
791     ASSERT_EQ(areaConfig->getMinInt32Value(), 0);
792     ASSERT_EQ(areaConfig->getMaxInt32Value(), 1);
793 
794     ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
795     ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(0));
796 }
797 
TEST_F(AidlVhalClientTest,testGetAllPropConfigsError)798 TEST_F(AidlVhalClientTest, testGetAllPropConfigsError) {
799     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
800 
801     auto result = getClient()->getAllPropConfigs();
802 
803     ASSERT_FALSE(result.ok());
804     ASSERT_EQ(result.error().code(), ErrorCode::INTERNAL_ERROR_FROM_VHAL);
805 }
806 
TEST_F(AidlVhalClientTest,testGetPropConfigs)807 TEST_F(AidlVhalClientTest, testGetPropConfigs) {
808     getVhal()->setPropConfigs({
809             VehiclePropConfig{
810                     .prop = TEST_PROP_ID,
811                     .areaConfigs = {{
812                             .areaId = TEST_AREA_ID,
813                             .minInt32Value = 0,
814                             .maxInt32Value = 1,
815                     }},
816             },
817             VehiclePropConfig{
818                     .prop = TEST_PROP_ID_2,
819             },
820     });
821 
822     std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
823     auto result = getClient()->getPropConfigs(propIds);
824 
825     ASSERT_EQ(getVhal()->getGetPropConfigPropIds(), propIds);
826     ASSERT_TRUE(result.ok());
827     std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
828 
829     ASSERT_EQ(configs.size(), static_cast<size_t>(2));
830     ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
831     ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(1));
832 
833     const IHalAreaConfig* areaConfig = configs[0]->getAreaConfigs();
834     ASSERT_EQ(areaConfig->getAreaId(), TEST_AREA_ID);
835     ASSERT_EQ(areaConfig->getMinInt32Value(), 0);
836     ASSERT_EQ(areaConfig->getMaxInt32Value(), 1);
837 
838     ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
839     ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(0));
840 }
841 
TEST_F(AidlVhalClientTest,testGetPropConfigsError)842 TEST_F(AidlVhalClientTest, testGetPropConfigsError) {
843     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
844 
845     std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
846     auto result = getClient()->getPropConfigs(propIds);
847 
848     ASSERT_FALSE(result.ok());
849 }
850 
TEST_F(AidlVhalClientTest,testSubscribe)851 TEST_F(AidlVhalClientTest, testSubscribe) {
852     std::vector<SubscribeOptions> options = {
853             {
854                     .propId = TEST_PROP_ID,
855                     .areaIds = {TEST_AREA_ID},
856                     .sampleRate = 1.0,
857             },
858             {
859                     .propId = TEST_PROP_ID_2,
860                     .sampleRate = 2.0,
861             },
862     };
863 
864     auto callback = std::make_shared<MockSubscriptionCallback>();
865     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
866     auto result = subscriptionClient->subscribe(options);
867 
868     ASSERT_TRUE(result.ok());
869     ASSERT_EQ(getVhal()->getSubscriptionOptions(), options);
870 
871     getVhal()->triggerOnPropertyEvent(std::vector<VehiclePropValue>{
872             {
873                     .prop = TEST_PROP_ID,
874                     .areaId = TEST_AREA_ID,
875                     .value.int32Values = {1},
876             },
877     });
878 
879     ASSERT_EQ(callback->getEventPropIds(), std::vector<int32_t>({TEST_PROP_ID}));
880 
881     getVhal()->triggerSetErrorEvent(std::vector<VehiclePropError>({
882             {
883                     .propId = TEST_PROP_ID,
884                     .areaId = TEST_AREA_ID,
885                     .errorCode = StatusCode::INTERNAL_ERROR,
886             },
887     }));
888 
889     auto errors = callback->getErrors();
890     ASSERT_EQ(errors.size(), static_cast<size_t>(1));
891     ASSERT_EQ(errors[0].propId, TEST_PROP_ID);
892     ASSERT_EQ(errors[0].areaId, TEST_AREA_ID);
893     ASSERT_EQ(errors[0].status, StatusCode::INTERNAL_ERROR);
894 }
895 
TEST_F(AidlVhalClientTest,testSubscribeError)896 TEST_F(AidlVhalClientTest, testSubscribeError) {
897     std::vector<SubscribeOptions> options = {
898             {
899                     .propId = TEST_PROP_ID,
900                     .areaIds = {TEST_AREA_ID},
901                     .sampleRate = 1.0,
902             },
903             {
904                     .propId = TEST_PROP_ID_2,
905                     .sampleRate = 2.0,
906             },
907     };
908 
909     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
910     auto callback = std::make_shared<MockSubscriptionCallback>();
911     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
912     auto result = subscriptionClient->subscribe(options);
913 
914     ASSERT_FALSE(result.ok());
915 }
916 
TEST_F(AidlVhalClientTest,testUnubscribe)917 TEST_F(AidlVhalClientTest, testUnubscribe) {
918     auto callback = std::make_shared<MockSubscriptionCallback>();
919     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
920     auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
921 
922     ASSERT_TRUE(result.ok());
923     ASSERT_EQ(getVhal()->getUnsubscribedPropIds(), std::vector<int32_t>({TEST_PROP_ID}));
924 }
925 
TEST_F(AidlVhalClientTest,testUnubscribeError)926 TEST_F(AidlVhalClientTest, testUnubscribeError) {
927     getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
928     auto callback = std::make_shared<MockSubscriptionCallback>();
929     auto subscriptionClient = getClient()->getSubscriptionClient(callback);
930     auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
931 
932     ASSERT_FALSE(result.ok());
933 }
934 
935 }  // namespace aidl_test
936 }  // namespace vhal
937 }  // namespace automotive
938 }  // namespace frameworks
939 }  // namespace android
940