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