blob: c45c000c3c6a11d8349606294163e25a005bf9da [file] [log] [blame]
Yu Shan726d51a2022-02-22 17:37:21 -08001/*
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#define LOG_TAG "VtsHalAutomotiveVehicle"
18
19#include <IVhalClient.h>
20#include <VehicleHalTypes.h>
21#include <VehicleUtils.h>
22#include <aidl/Gtest.h>
23#include <aidl/Vintf.h>
24#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
25#include <android-base/stringprintf.h>
26#include <android-base/thread_annotations.h>
27#include <android/binder_process.h>
Yu Shan928062c2024-01-25 17:40:41 -080028#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
Yu Shan726d51a2022-02-22 17:37:21 -080029#include <gtest/gtest.h>
30#include <hidl/GtestPrinter.h>
31#include <hidl/ServiceManagement.h>
32#include <inttypes.h>
33#include <utils/Log.h>
Yu Shan4569ef52022-03-18 14:34:25 -070034#include <utils/SystemClock.h>
Yu Shan726d51a2022-02-22 17:37:21 -080035
36#include <chrono>
37#include <mutex>
Yu Shan62fe8822024-01-24 16:14:21 -080038#include <thread>
Yu Shan726d51a2022-02-22 17:37:21 -080039#include <unordered_map>
40#include <unordered_set>
41#include <vector>
42
43using ::aidl::android::hardware::automotive::vehicle::IVehicle;
44using ::aidl::android::hardware::automotive::vehicle::StatusCode;
45using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
46using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
47using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
48using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
Yu Shan62fe8822024-01-24 16:14:21 -080049using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
Yu Shan726d51a2022-02-22 17:37:21 -080050using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
51using ::android::getAidlHalInstanceNames;
Yu Shan62fe8822024-01-24 16:14:21 -080052using ::android::uptimeMillis;
Yu Shan726d51a2022-02-22 17:37:21 -080053using ::android::base::ScopedLockAssertion;
54using ::android::base::StringPrintf;
55using ::android::frameworks::automotive::vhal::HalPropError;
56using ::android::frameworks::automotive::vhal::IHalPropConfig;
57using ::android::frameworks::automotive::vhal::IHalPropValue;
58using ::android::frameworks::automotive::vhal::ISubscriptionCallback;
59using ::android::frameworks::automotive::vhal::IVhalClient;
60using ::android::hardware::getAllHalInstanceNames;
61using ::android::hardware::Sanitize;
62using ::android::hardware::automotive::vehicle::toInt;
Yu Shan62fe8822024-01-24 16:14:21 -080063using ::android::hardware::automotive::vehicle::VhalResult;
Yu Shan726d51a2022-02-22 17:37:21 -080064
65constexpr int32_t kInvalidProp = 0x31600207;
Yu Shan62fe8822024-01-24 16:14:21 -080066// The timeout for retrying getting prop value after setting prop value.
67constexpr int64_t kRetryGetPropAfterSetPropTimeoutMillis = 10'000;
Yu Shan726d51a2022-02-22 17:37:21 -080068
69struct ServiceDescriptor {
70 std::string name;
71 bool isAidlService;
72};
73
74class VtsVehicleCallback final : public ISubscriptionCallback {
75 private:
76 std::mutex mLock;
77 std::unordered_map<int32_t, size_t> mEventsCount GUARDED_BY(mLock);
Yu Shan4569ef52022-03-18 14:34:25 -070078 std::unordered_map<int32_t, std::vector<int64_t>> mEventTimestamps GUARDED_BY(mLock);
Yu Shan726d51a2022-02-22 17:37:21 -080079 std::condition_variable mEventCond;
80
81 public:
82 void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) override {
83 {
84 std::lock_guard<std::mutex> lockGuard(mLock);
85 for (auto& value : values) {
Yu Shan4569ef52022-03-18 14:34:25 -070086 int32_t propId = value->getPropId();
87 mEventsCount[propId] += 1;
88 mEventTimestamps[propId].push_back(value->getTimestamp());
Yu Shan726d51a2022-02-22 17:37:21 -080089 }
90 }
91 mEventCond.notify_one();
92 }
93
94 void onPropertySetError([[maybe_unused]] const std::vector<HalPropError>& errors) override {
95 // Do nothing.
96 }
97
98 template <class Rep, class Period>
99 bool waitForExpectedEvents(int32_t propId, size_t expectedEvents,
100 const std::chrono::duration<Rep, Period>& timeout) {
101 std::unique_lock<std::mutex> uniqueLock(mLock);
102 return mEventCond.wait_for(uniqueLock, timeout, [this, propId, expectedEvents] {
103 ScopedLockAssertion lockAssertion(mLock);
104 return mEventsCount[propId] >= expectedEvents;
105 });
106 }
107
Yu Shan4569ef52022-03-18 14:34:25 -0700108 std::vector<int64_t> getEventTimestamps(int32_t propId) {
109 {
110 std::lock_guard<std::mutex> lockGuard(mLock);
111 return mEventTimestamps[propId];
112 }
113 }
114
Yu Shan726d51a2022-02-22 17:37:21 -0800115 void reset() {
116 std::lock_guard<std::mutex> lockGuard(mLock);
117 mEventsCount.clear();
118 }
119};
120
121class VtsHalAutomotiveVehicleTargetTest : public testing::TestWithParam<ServiceDescriptor> {
Yu Shanda7a4dd2023-10-09 14:43:36 -0700122protected:
123 bool checkIsSupported(int32_t propertyId);
Yu Shan62fe8822024-01-24 16:14:21 -0800124 VehiclePropertyStatus getStatus(const IHalPropValue& halPropValue);
125 bool isUnavailable(const VhalResult<std::unique_ptr<IHalPropValue>>& result);
126 bool isResultOkayWithValue(const VhalResult<std::unique_ptr<IHalPropValue>>& result,
127 int32_t value);
Yu Shan726d51a2022-02-22 17:37:21 -0800128
Yu Shanda7a4dd2023-10-09 14:43:36 -0700129public:
130 virtual void SetUp() override {
131 auto descriptor = GetParam();
132 if (descriptor.isAidlService) {
133 mVhalClient = IVhalClient::tryCreateAidlClient(descriptor.name.c_str());
134 } else {
135 mVhalClient = IVhalClient::tryCreateHidlClient(descriptor.name.c_str());
136 }
Yu Shan726d51a2022-02-22 17:37:21 -0800137
Yu Shanda7a4dd2023-10-09 14:43:36 -0700138 ASSERT_NE(mVhalClient, nullptr) << "Failed to connect to VHAL";
139
140 mCallback = std::make_shared<VtsVehicleCallback>();
141 }
Yu Shan726d51a2022-02-22 17:37:21 -0800142
143 static bool isBooleanGlobalProp(int32_t property) {
144 return (property & toInt(VehiclePropertyType::MASK)) ==
145 toInt(VehiclePropertyType::BOOLEAN) &&
146 (property & toInt(VehicleArea::MASK)) == toInt(VehicleArea::GLOBAL);
147 }
148
149 protected:
150 std::shared_ptr<IVhalClient> mVhalClient;
151 std::shared_ptr<VtsVehicleCallback> mCallback;
152};
153
154TEST_P(VtsHalAutomotiveVehicleTargetTest, useAidlBackend) {
155 if (!mVhalClient->isAidlVhal()) {
156 GTEST_SKIP() << "AIDL backend is not available, HIDL backend is used instead";
157 }
158}
159
160TEST_P(VtsHalAutomotiveVehicleTargetTest, useHidlBackend) {
161 if (mVhalClient->isAidlVhal()) {
162 GTEST_SKIP() << "AIDL backend is available, HIDL backend is not used";
163 }
164}
165
Yu Shanda7a4dd2023-10-09 14:43:36 -0700166// Test getAllPropConfigs() returns at least 1 property configs.
Yu Shan726d51a2022-02-22 17:37:21 -0800167TEST_P(VtsHalAutomotiveVehicleTargetTest, getAllPropConfigs) {
168 ALOGD("VtsHalAutomotiveVehicleTargetTest::getAllPropConfigs");
169
170 auto result = mVhalClient->getAllPropConfigs();
171
172 ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
173 << result.error().message();
Yu Shanda7a4dd2023-10-09 14:43:36 -0700174 ASSERT_GE(result.value().size(), 1u)
175 << StringPrintf("Expect to get at least 1 property config, got %zu",
176 result.value().size());
Yu Shan726d51a2022-02-22 17:37:21 -0800177}
178
Yu Shanda7a4dd2023-10-09 14:43:36 -0700179// Test getPropConfigs() can query properties returned by getAllPropConfigs.
180TEST_P(VtsHalAutomotiveVehicleTargetTest, getPropConfigsWithValidProps) {
Yu Shan726d51a2022-02-22 17:37:21 -0800181 ALOGD("VtsHalAutomotiveVehicleTargetTest::getRequiredPropConfigs");
182
Yu Shanda7a4dd2023-10-09 14:43:36 -0700183 std::vector<int32_t> properties;
184 auto result = mVhalClient->getAllPropConfigs();
Yu Shan726d51a2022-02-22 17:37:21 -0800185
Yu Shanda7a4dd2023-10-09 14:43:36 -0700186 ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
187 << result.error().message();
188 for (const auto& cfgPtr : result.value()) {
189 properties.push_back(cfgPtr->getPropId());
190 }
191
192 result = mVhalClient->getPropConfigs(properties);
Yu Shan726d51a2022-02-22 17:37:21 -0800193
194 ASSERT_TRUE(result.ok()) << "Failed to get required property config, error: "
195 << result.error().message();
Yu Shanda7a4dd2023-10-09 14:43:36 -0700196 ASSERT_EQ(result.value().size(), properties.size())
197 << StringPrintf("Expect to get exactly %zu configs, got %zu",
198 properties.size(), result.value().size());
Yu Shan726d51a2022-02-22 17:37:21 -0800199}
200
201// Test getPropConfig() with an invalid propertyId returns an error code.
202TEST_P(VtsHalAutomotiveVehicleTargetTest, getPropConfigsWithInvalidProp) {
203 ALOGD("VtsHalAutomotiveVehicleTargetTest::getPropConfigsWithInvalidProp");
204
205 auto result = mVhalClient->getPropConfigs({kInvalidProp});
206
207 ASSERT_FALSE(result.ok()) << StringPrintf(
208 "Expect failure to get prop configs for invalid prop: %" PRId32, kInvalidProp);
209 ASSERT_NE(result.error().message(), "") << "Expect error message not to be empty";
210}
211
212// Test get() return current value for properties.
213TEST_P(VtsHalAutomotiveVehicleTargetTest, get) {
214 ALOGD("VtsHalAutomotiveVehicleTargetTest::get");
215
216 int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700217 if (!checkIsSupported(propId)) {
218 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
219 }
Yu Shan726d51a2022-02-22 17:37:21 -0800220 auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
221
222 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
223 ", error: %s",
224 propId, result.error().message().c_str());
225 ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
226}
227
228// Test get() with an invalid propertyId return an error codes.
229TEST_P(VtsHalAutomotiveVehicleTargetTest, getInvalidProp) {
230 ALOGD("VtsHalAutomotiveVehicleTargetTest::getInvalidProp");
231
232 auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(kInvalidProp));
233
234 ASSERT_FALSE(result.ok()) << StringPrintf(
235 "Expect failure to get property for invalid prop: %" PRId32, kInvalidProp);
236}
237
Yu Shan62fe8822024-01-24 16:14:21 -0800238VehiclePropertyStatus VtsHalAutomotiveVehicleTargetTest::getStatus(
239 const IHalPropValue& halPropValue) {
240 if (mVhalClient->isAidlVhal()) {
241 return reinterpret_cast<
242 const aidl::android::hardware::automotive::vehicle::VehiclePropValue*>(
243 halPropValue.toVehiclePropValue())
244 ->status;
245 }
246 return static_cast<VehiclePropertyStatus>(
247 reinterpret_cast<const android::hardware::automotive::vehicle::V2_0::VehiclePropValue*>(
248 halPropValue.toVehiclePropValue())
249 ->status);
250}
251
252bool VtsHalAutomotiveVehicleTargetTest::isResultOkayWithValue(
253 const VhalResult<std::unique_ptr<IHalPropValue>>& result, int32_t value) {
254 return result.ok() && result.value() != nullptr &&
255 getStatus(*(result.value())) == VehiclePropertyStatus::AVAILABLE &&
256 result.value()->getInt32Values().size() == 1 &&
257 result.value()->getInt32Values()[0] == value;
258}
259
260bool VtsHalAutomotiveVehicleTargetTest::isUnavailable(
261 const VhalResult<std::unique_ptr<IHalPropValue>>& result) {
262 if (!result.ok()) {
263 return result.error().code() == StatusCode::NOT_AVAILABLE;
264 }
265 if (result.value() != nullptr &&
266 getStatus(*(result.value())) == VehiclePropertyStatus::UNAVAILABLE) {
267 return true;
268 }
269
270 return false;
271}
272
Yu Shan726d51a2022-02-22 17:37:21 -0800273// Test set() on read_write properties.
274TEST_P(VtsHalAutomotiveVehicleTargetTest, setProp) {
275 ALOGD("VtsHalAutomotiveVehicleTargetTest::setProp");
276
277 // skip hvac related properties
278 std::unordered_set<int32_t> hvacProps = {toInt(VehicleProperty::HVAC_DEFROSTER),
279 toInt(VehicleProperty::HVAC_AC_ON),
280 toInt(VehicleProperty::HVAC_MAX_AC_ON),
281 toInt(VehicleProperty::HVAC_MAX_DEFROST_ON),
282 toInt(VehicleProperty::HVAC_RECIRC_ON),
283 toInt(VehicleProperty::HVAC_DUAL_ON),
284 toInt(VehicleProperty::HVAC_AUTO_ON),
285 toInt(VehicleProperty::HVAC_POWER_ON),
286 toInt(VehicleProperty::HVAC_AUTO_RECIRC_ON),
287 toInt(VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON)};
288 auto result = mVhalClient->getAllPropConfigs();
289 ASSERT_TRUE(result.ok());
290
291 for (const auto& cfgPtr : result.value()) {
292 const IHalPropConfig& cfg = *cfgPtr;
293 int32_t propId = cfg.getPropId();
294 // test on boolean and writable property
295 if (cfg.getAccess() == toInt(VehiclePropertyAccess::READ_WRITE) &&
296 isBooleanGlobalProp(propId) && !hvacProps.count(propId)) {
297 auto propToGet = mVhalClient->createHalPropValue(propId);
298 auto getValueResult = mVhalClient->getValueSync(*propToGet);
299
Yu Shan62fe8822024-01-24 16:14:21 -0800300 if (isUnavailable(getValueResult)) {
301 ALOGW("getProperty for %" PRId32
302 " returns NOT_AVAILABLE, "
303 "skip testing setProp",
304 propId);
305 return;
306 }
307
Yu Shan726d51a2022-02-22 17:37:21 -0800308 ASSERT_TRUE(getValueResult.ok())
309 << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s",
310 propId, getValueResult.error().message().c_str());
311 ASSERT_NE(getValueResult.value(), nullptr)
312 << StringPrintf("Result value must not be null for property: %" PRId32, propId);
313
314 const IHalPropValue& value = *getValueResult.value();
315 size_t intValueSize = value.getInt32Values().size();
316 ASSERT_EQ(intValueSize, 1u) << StringPrintf(
317 "Expect exactly 1 int value for boolean property: %" PRId32 ", got %zu", propId,
318 intValueSize);
319
Yu Shan62fe8822024-01-24 16:14:21 -0800320 int32_t setValue = value.getInt32Values()[0] == 1 ? 0 : 1;
Yu Shan726d51a2022-02-22 17:37:21 -0800321 auto propToSet = mVhalClient->createHalPropValue(propId);
322 propToSet->setInt32Values({setValue});
323 auto setValueResult = mVhalClient->setValueSync(*propToSet);
324
Yu Shan62fe8822024-01-24 16:14:21 -0800325 if (!setValueResult.ok() &&
326 setValueResult.error().code() == StatusCode::NOT_AVAILABLE) {
327 ALOGW("setProperty for %" PRId32
328 " returns NOT_AVAILABLE, "
329 "skip verifying getProperty returns the same value",
330 propId);
331 return;
332 }
333
Yu Shan726d51a2022-02-22 17:37:21 -0800334 ASSERT_TRUE(setValueResult.ok())
335 << StringPrintf("Failed to set value for property: %" PRId32 ", error: %s",
336 propId, setValueResult.error().message().c_str());
Yu Shan62fe8822024-01-24 16:14:21 -0800337 // Retry getting the value until we pass the timeout. getValue might not return
338 // the expected value immediately since setValue is async.
339 auto timeoutMillis = uptimeMillis() + kRetryGetPropAfterSetPropTimeoutMillis;
Yu Shan726d51a2022-02-22 17:37:21 -0800340
Yu Shan62fe8822024-01-24 16:14:21 -0800341 while (true) {
342 getValueResult = mVhalClient->getValueSync(*propToGet);
343 if (isResultOkayWithValue(getValueResult, setValue)) {
344 break;
345 }
346 if (uptimeMillis() >= timeoutMillis) {
347 // Reach timeout, the following assert should fail.
348 break;
349 }
350 // Sleep for 100ms between each getValueSync retry.
351 std::this_thread::sleep_for(std::chrono::milliseconds(100));
352 }
353
354 if (isUnavailable(getValueResult)) {
355 ALOGW("getProperty for %" PRId32
356 " returns NOT_AVAILABLE, "
357 "skip verifying the return value",
358 propId);
359 return;
360 }
361
Yu Shan726d51a2022-02-22 17:37:21 -0800362 ASSERT_TRUE(getValueResult.ok())
363 << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s",
364 propId, getValueResult.error().message().c_str());
365 ASSERT_NE(getValueResult.value(), nullptr)
366 << StringPrintf("Result value must not be null for property: %" PRId32, propId);
367 ASSERT_EQ(getValueResult.value()->getInt32Values(), std::vector<int32_t>({setValue}))
368 << StringPrintf("Boolean value not updated after set for property: %" PRId32,
369 propId);
370 }
371 }
372}
373
374// Test set() on an read_only property.
375TEST_P(VtsHalAutomotiveVehicleTargetTest, setNotWritableProp) {
376 ALOGD("VtsHalAutomotiveVehicleTargetTest::setNotWritableProp");
377
378 int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700379 if (!checkIsSupported(propId)) {
380 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
381 }
382
Yu Shan726d51a2022-02-22 17:37:21 -0800383 auto getValueResult = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
384 ASSERT_TRUE(getValueResult.ok())
385 << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s", propId,
386 getValueResult.error().message().c_str());
387
388 auto setValueResult = mVhalClient->setValueSync(*getValueResult.value());
389
390 ASSERT_FALSE(setValueResult.ok()) << "Expect set a read-only value to fail";
Yu Shan24fee7b2022-03-03 15:10:51 -0800391 ASSERT_EQ(setValueResult.error().code(), StatusCode::ACCESS_DENIED);
Yu Shan726d51a2022-02-22 17:37:21 -0800392}
393
394// Test subscribe() and unsubscribe().
395TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeAndUnsubscribe) {
396 ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeAndUnsubscribe");
397
398 int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700399 if (!checkIsSupported(propId)) {
400 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
401 }
Yu Shan726d51a2022-02-22 17:37:21 -0800402
Yu Shan4569ef52022-03-18 14:34:25 -0700403 auto propConfigsResult = mVhalClient->getPropConfigs({propId});
404
405 ASSERT_TRUE(propConfigsResult.ok()) << "Failed to get property config for PERF_VEHICLE_SPEED: "
406 << "error: " << propConfigsResult.error().message();
407 ASSERT_EQ(propConfigsResult.value().size(), 1u)
408 << "Expect to return 1 config for PERF_VEHICLE_SPEED";
409 auto& propConfig = propConfigsResult.value()[0];
410 float minSampleRate = propConfig->getMinSampleRate();
411 float maxSampleRate = propConfig->getMaxSampleRate();
412
413 if (minSampleRate < 1) {
414 GTEST_SKIP() << "Sample rate for vehicle speed < 1 times/sec, skip test since it would "
415 "take too long";
416 }
Yu Shan726d51a2022-02-22 17:37:21 -0800417
418 auto client = mVhalClient->getSubscriptionClient(mCallback);
419 ASSERT_NE(client, nullptr) << "Failed to get subscription client";
420
Yu Shan4569ef52022-03-18 14:34:25 -0700421 auto result = client->subscribe({{.propId = propId, .sampleRate = minSampleRate}});
Yu Shan726d51a2022-02-22 17:37:21 -0800422
423 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to subscribe to property: %" PRId32
424 ", error: %s",
425 propId, result.error().message().c_str());
Yu Shan4569ef52022-03-18 14:34:25 -0700426
427 if (mVhalClient->isAidlVhal()) {
428 // Skip checking timestamp for HIDL because the behavior for sample rate and timestamp is
429 // only specified clearly for AIDL.
430
431 // Timeout is 2 seconds, which gives a 1 second buffer.
432 ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, std::floor(minSampleRate),
433 std::chrono::seconds(2)))
434 << "Didn't get enough events for subscribing to minSampleRate";
435 }
436
437 result = client->subscribe({{.propId = propId, .sampleRate = maxSampleRate}});
438
439 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to subscribe to property: %" PRId32
440 ", error: %s",
441 propId, result.error().message().c_str());
442
443 if (mVhalClient->isAidlVhal()) {
444 ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, std::floor(maxSampleRate),
445 std::chrono::seconds(2)))
446 << "Didn't get enough events for subscribing to maxSampleRate";
447
448 std::unordered_set<int64_t> timestamps;
449 // Event event should have a different timestamp.
450 for (const int64_t& eventTimestamp : mCallback->getEventTimestamps(propId)) {
451 ASSERT_TRUE(timestamps.find(eventTimestamp) == timestamps.end())
452 << "two events for the same property must not have the same timestamp";
453 timestamps.insert(eventTimestamp);
454 }
455 }
Yu Shan726d51a2022-02-22 17:37:21 -0800456
457 result = client->unsubscribe({propId});
458 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to unsubscribe to property: %" PRId32
459 ", error: %s",
460 propId, result.error().message().c_str());
461
462 mCallback->reset();
463 ASSERT_FALSE(mCallback->waitForExpectedEvents(propId, 10, std::chrono::seconds(1)))
464 << "Expect not to get events after unsubscription";
465}
466
467// Test subscribe() with an invalid property.
468TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeInvalidProp) {
469 ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeInvalidProp");
470
471 std::vector<SubscribeOptions> options = {
472 SubscribeOptions{.propId = kInvalidProp, .sampleRate = 10.0}};
473
474 auto client = mVhalClient->getSubscriptionClient(mCallback);
475 ASSERT_NE(client, nullptr) << "Failed to get subscription client";
476
477 auto result = client->subscribe(options);
478
479 ASSERT_FALSE(result.ok()) << StringPrintf("Expect subscribing to property: %" PRId32 " to fail",
480 kInvalidProp);
481}
482
Yu Shan4569ef52022-03-18 14:34:25 -0700483// Test the timestamp returned in GetValues results is the timestamp when the value is retrieved.
484TEST_P(VtsHalAutomotiveVehicleTargetTest, testGetValuesTimestampAIDL) {
485 if (!mVhalClient->isAidlVhal()) {
486 GTEST_SKIP() << "Skip checking timestamp for HIDL because the behavior is only specified "
487 "for AIDL";
488 }
489
490 int32_t propId = toInt(VehicleProperty::PARKING_BRAKE_ON);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700491 if (!checkIsSupported(propId)) {
492 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
493 }
Yu Shan4569ef52022-03-18 14:34:25 -0700494 auto prop = mVhalClient->createHalPropValue(propId);
495
496 auto result = mVhalClient->getValueSync(*prop);
497
498 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
499 ", error: %s",
500 propId, result.error().message().c_str());
501 ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
502 ASSERT_EQ(result.value()->getInt32Values().size(), 1u) << "Result must contain 1 int value";
503
504 bool parkBrakeOnValue1 = (result.value()->getInt32Values()[0] == 1);
505 int64_t timestampValue1 = result.value()->getTimestamp();
506
507 result = mVhalClient->getValueSync(*prop);
508
509 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
510 ", error: %s",
511 propId, result.error().message().c_str());
512 ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
513 ASSERT_EQ(result.value()->getInt32Values().size(), 1u) << "Result must contain 1 int value";
514
515 bool parkBarkeOnValue2 = (result.value()->getInt32Values()[0] == 1);
516 int64_t timestampValue2 = result.value()->getTimestamp();
517
518 if (parkBarkeOnValue2 == parkBrakeOnValue1) {
519 ASSERT_EQ(timestampValue2, timestampValue1)
520 << "getValue result must contain a timestamp updated when the value was updated, if"
521 "the value does not change, expect the same timestamp";
522 } else {
523 ASSERT_GT(timestampValue2, timestampValue1)
524 << "getValue result must contain a timestamp updated when the value was updated, if"
525 "the value changes, expect the newer value has a larger timestamp";
526 }
527}
528
Yu Shanda7a4dd2023-10-09 14:43:36 -0700529bool VtsHalAutomotiveVehicleTargetTest::checkIsSupported(int32_t propertyId) {
530 auto result = mVhalClient->getPropConfigs({propertyId});
531 return result.ok();
532}
533
Yu Shan726d51a2022-02-22 17:37:21 -0800534std::vector<ServiceDescriptor> getDescriptors() {
535 std::vector<ServiceDescriptor> descriptors;
536 for (std::string name : getAidlHalInstanceNames(IVehicle::descriptor)) {
537 descriptors.push_back({
538 .name = name,
539 .isAidlService = true,
540 });
541 }
Yu Shan928062c2024-01-25 17:40:41 -0800542 for (std::string name : getAllHalInstanceNames(
543 android::hardware::automotive::vehicle::V2_0::IVehicle::descriptor)) {
Yu Shan726d51a2022-02-22 17:37:21 -0800544 descriptors.push_back({
545 .name = name,
546 .isAidlService = false,
547 });
548 }
549 return descriptors;
550}
551
552GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VtsHalAutomotiveVehicleTargetTest);
553
554INSTANTIATE_TEST_SUITE_P(PerInstance, VtsHalAutomotiveVehicleTargetTest,
555 testing::ValuesIn(getDescriptors()),
556 [](const testing::TestParamInfo<ServiceDescriptor>& info) {
557 std::string name = "";
558 if (info.param.isAidlService) {
559 name += "aidl_";
560 } else {
561 name += "hidl_";
562 }
563 name += info.param.name;
564 return Sanitize(name);
565 });
566
567int main(int argc, char** argv) {
568 ::testing::InitGoogleTest(&argc, argv);
569 ABinderProcess_setThreadPoolMaxThreadCount(1);
570 return RUN_ALL_TESTS();
571}