blob: f8ef8cba61aadd23164dfdc044fb1b155fd101ab [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>
38#include <unordered_map>
39#include <unordered_set>
40#include <vector>
41
42using ::aidl::android::hardware::automotive::vehicle::IVehicle;
43using ::aidl::android::hardware::automotive::vehicle::StatusCode;
44using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
45using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
46using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
47using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
48using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
49using ::android::getAidlHalInstanceNames;
50using ::android::base::ScopedLockAssertion;
51using ::android::base::StringPrintf;
52using ::android::frameworks::automotive::vhal::HalPropError;
53using ::android::frameworks::automotive::vhal::IHalPropConfig;
54using ::android::frameworks::automotive::vhal::IHalPropValue;
55using ::android::frameworks::automotive::vhal::ISubscriptionCallback;
56using ::android::frameworks::automotive::vhal::IVhalClient;
57using ::android::hardware::getAllHalInstanceNames;
58using ::android::hardware::Sanitize;
59using ::android::hardware::automotive::vehicle::toInt;
60
61constexpr int32_t kInvalidProp = 0x31600207;
62
63struct ServiceDescriptor {
64 std::string name;
65 bool isAidlService;
66};
67
68class VtsVehicleCallback final : public ISubscriptionCallback {
69 private:
70 std::mutex mLock;
71 std::unordered_map<int32_t, size_t> mEventsCount GUARDED_BY(mLock);
Yu Shan4569ef52022-03-18 14:34:25 -070072 std::unordered_map<int32_t, std::vector<int64_t>> mEventTimestamps GUARDED_BY(mLock);
Yu Shan726d51a2022-02-22 17:37:21 -080073 std::condition_variable mEventCond;
74
75 public:
76 void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) override {
77 {
78 std::lock_guard<std::mutex> lockGuard(mLock);
79 for (auto& value : values) {
Yu Shan4569ef52022-03-18 14:34:25 -070080 int32_t propId = value->getPropId();
81 mEventsCount[propId] += 1;
82 mEventTimestamps[propId].push_back(value->getTimestamp());
Yu Shan726d51a2022-02-22 17:37:21 -080083 }
84 }
85 mEventCond.notify_one();
86 }
87
88 void onPropertySetError([[maybe_unused]] const std::vector<HalPropError>& errors) override {
89 // Do nothing.
90 }
91
92 template <class Rep, class Period>
93 bool waitForExpectedEvents(int32_t propId, size_t expectedEvents,
94 const std::chrono::duration<Rep, Period>& timeout) {
95 std::unique_lock<std::mutex> uniqueLock(mLock);
96 return mEventCond.wait_for(uniqueLock, timeout, [this, propId, expectedEvents] {
97 ScopedLockAssertion lockAssertion(mLock);
98 return mEventsCount[propId] >= expectedEvents;
99 });
100 }
101
Yu Shan4569ef52022-03-18 14:34:25 -0700102 std::vector<int64_t> getEventTimestamps(int32_t propId) {
103 {
104 std::lock_guard<std::mutex> lockGuard(mLock);
105 return mEventTimestamps[propId];
106 }
107 }
108
Yu Shan726d51a2022-02-22 17:37:21 -0800109 void reset() {
110 std::lock_guard<std::mutex> lockGuard(mLock);
111 mEventsCount.clear();
112 }
113};
114
115class VtsHalAutomotiveVehicleTargetTest : public testing::TestWithParam<ServiceDescriptor> {
Yu Shanda7a4dd2023-10-09 14:43:36 -0700116protected:
117 bool checkIsSupported(int32_t propertyId);
Yu Shan726d51a2022-02-22 17:37:21 -0800118
Yu Shanda7a4dd2023-10-09 14:43:36 -0700119public:
120 virtual void SetUp() override {
121 auto descriptor = GetParam();
122 if (descriptor.isAidlService) {
123 mVhalClient = IVhalClient::tryCreateAidlClient(descriptor.name.c_str());
124 } else {
125 mVhalClient = IVhalClient::tryCreateHidlClient(descriptor.name.c_str());
126 }
Yu Shan726d51a2022-02-22 17:37:21 -0800127
Yu Shanda7a4dd2023-10-09 14:43:36 -0700128 ASSERT_NE(mVhalClient, nullptr) << "Failed to connect to VHAL";
129
130 mCallback = std::make_shared<VtsVehicleCallback>();
131 }
Yu Shan726d51a2022-02-22 17:37:21 -0800132
133 static bool isBooleanGlobalProp(int32_t property) {
134 return (property & toInt(VehiclePropertyType::MASK)) ==
135 toInt(VehiclePropertyType::BOOLEAN) &&
136 (property & toInt(VehicleArea::MASK)) == toInt(VehicleArea::GLOBAL);
137 }
138
139 protected:
140 std::shared_ptr<IVhalClient> mVhalClient;
141 std::shared_ptr<VtsVehicleCallback> mCallback;
142};
143
144TEST_P(VtsHalAutomotiveVehicleTargetTest, useAidlBackend) {
145 if (!mVhalClient->isAidlVhal()) {
146 GTEST_SKIP() << "AIDL backend is not available, HIDL backend is used instead";
147 }
148}
149
150TEST_P(VtsHalAutomotiveVehicleTargetTest, useHidlBackend) {
151 if (mVhalClient->isAidlVhal()) {
152 GTEST_SKIP() << "AIDL backend is available, HIDL backend is not used";
153 }
154}
155
Yu Shanda7a4dd2023-10-09 14:43:36 -0700156// Test getAllPropConfigs() returns at least 1 property configs.
Yu Shan726d51a2022-02-22 17:37:21 -0800157TEST_P(VtsHalAutomotiveVehicleTargetTest, getAllPropConfigs) {
158 ALOGD("VtsHalAutomotiveVehicleTargetTest::getAllPropConfigs");
159
160 auto result = mVhalClient->getAllPropConfigs();
161
162 ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
163 << result.error().message();
Yu Shanda7a4dd2023-10-09 14:43:36 -0700164 ASSERT_GE(result.value().size(), 1u)
165 << StringPrintf("Expect to get at least 1 property config, got %zu",
166 result.value().size());
Yu Shan726d51a2022-02-22 17:37:21 -0800167}
168
Yu Shanda7a4dd2023-10-09 14:43:36 -0700169// Test getPropConfigs() can query properties returned by getAllPropConfigs.
170TEST_P(VtsHalAutomotiveVehicleTargetTest, getPropConfigsWithValidProps) {
Yu Shan726d51a2022-02-22 17:37:21 -0800171 ALOGD("VtsHalAutomotiveVehicleTargetTest::getRequiredPropConfigs");
172
Yu Shanda7a4dd2023-10-09 14:43:36 -0700173 std::vector<int32_t> properties;
174 auto result = mVhalClient->getAllPropConfigs();
Yu Shan726d51a2022-02-22 17:37:21 -0800175
Yu Shanda7a4dd2023-10-09 14:43:36 -0700176 ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
177 << result.error().message();
178 for (const auto& cfgPtr : result.value()) {
179 properties.push_back(cfgPtr->getPropId());
180 }
181
182 result = mVhalClient->getPropConfigs(properties);
Yu Shan726d51a2022-02-22 17:37:21 -0800183
184 ASSERT_TRUE(result.ok()) << "Failed to get required property config, error: "
185 << result.error().message();
Yu Shanda7a4dd2023-10-09 14:43:36 -0700186 ASSERT_EQ(result.value().size(), properties.size())
187 << StringPrintf("Expect to get exactly %zu configs, got %zu",
188 properties.size(), result.value().size());
Yu Shan726d51a2022-02-22 17:37:21 -0800189}
190
191// Test getPropConfig() with an invalid propertyId returns an error code.
192TEST_P(VtsHalAutomotiveVehicleTargetTest, getPropConfigsWithInvalidProp) {
193 ALOGD("VtsHalAutomotiveVehicleTargetTest::getPropConfigsWithInvalidProp");
194
195 auto result = mVhalClient->getPropConfigs({kInvalidProp});
196
197 ASSERT_FALSE(result.ok()) << StringPrintf(
198 "Expect failure to get prop configs for invalid prop: %" PRId32, kInvalidProp);
199 ASSERT_NE(result.error().message(), "") << "Expect error message not to be empty";
200}
201
202// Test get() return current value for properties.
203TEST_P(VtsHalAutomotiveVehicleTargetTest, get) {
204 ALOGD("VtsHalAutomotiveVehicleTargetTest::get");
205
206 int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700207 if (!checkIsSupported(propId)) {
208 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
209 }
Yu Shan726d51a2022-02-22 17:37:21 -0800210 auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
211
212 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
213 ", error: %s",
214 propId, result.error().message().c_str());
215 ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
216}
217
218// Test get() with an invalid propertyId return an error codes.
219TEST_P(VtsHalAutomotiveVehicleTargetTest, getInvalidProp) {
220 ALOGD("VtsHalAutomotiveVehicleTargetTest::getInvalidProp");
221
222 auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(kInvalidProp));
223
224 ASSERT_FALSE(result.ok()) << StringPrintf(
225 "Expect failure to get property for invalid prop: %" PRId32, kInvalidProp);
226}
227
228// Test set() on read_write properties.
229TEST_P(VtsHalAutomotiveVehicleTargetTest, setProp) {
230 ALOGD("VtsHalAutomotiveVehicleTargetTest::setProp");
231
232 // skip hvac related properties
233 std::unordered_set<int32_t> hvacProps = {toInt(VehicleProperty::HVAC_DEFROSTER),
234 toInt(VehicleProperty::HVAC_AC_ON),
235 toInt(VehicleProperty::HVAC_MAX_AC_ON),
236 toInt(VehicleProperty::HVAC_MAX_DEFROST_ON),
237 toInt(VehicleProperty::HVAC_RECIRC_ON),
238 toInt(VehicleProperty::HVAC_DUAL_ON),
239 toInt(VehicleProperty::HVAC_AUTO_ON),
240 toInt(VehicleProperty::HVAC_POWER_ON),
241 toInt(VehicleProperty::HVAC_AUTO_RECIRC_ON),
242 toInt(VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON)};
243 auto result = mVhalClient->getAllPropConfigs();
244 ASSERT_TRUE(result.ok());
245
246 for (const auto& cfgPtr : result.value()) {
247 const IHalPropConfig& cfg = *cfgPtr;
248 int32_t propId = cfg.getPropId();
249 // test on boolean and writable property
250 if (cfg.getAccess() == toInt(VehiclePropertyAccess::READ_WRITE) &&
251 isBooleanGlobalProp(propId) && !hvacProps.count(propId)) {
252 auto propToGet = mVhalClient->createHalPropValue(propId);
253 auto getValueResult = mVhalClient->getValueSync(*propToGet);
254
255 ASSERT_TRUE(getValueResult.ok())
256 << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s",
257 propId, getValueResult.error().message().c_str());
258 ASSERT_NE(getValueResult.value(), nullptr)
259 << StringPrintf("Result value must not be null for property: %" PRId32, propId);
260
261 const IHalPropValue& value = *getValueResult.value();
262 size_t intValueSize = value.getInt32Values().size();
263 ASSERT_EQ(intValueSize, 1u) << StringPrintf(
264 "Expect exactly 1 int value for boolean property: %" PRId32 ", got %zu", propId,
265 intValueSize);
266
267 int setValue = value.getInt32Values()[0] == 1 ? 0 : 1;
268 auto propToSet = mVhalClient->createHalPropValue(propId);
269 propToSet->setInt32Values({setValue});
270 auto setValueResult = mVhalClient->setValueSync(*propToSet);
271
272 ASSERT_TRUE(setValueResult.ok())
273 << StringPrintf("Failed to set value for property: %" PRId32 ", error: %s",
274 propId, setValueResult.error().message().c_str());
275
276 // check set success
277 getValueResult = mVhalClient->getValueSync(*propToGet);
278 ASSERT_TRUE(getValueResult.ok())
279 << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s",
280 propId, getValueResult.error().message().c_str());
281 ASSERT_NE(getValueResult.value(), nullptr)
282 << StringPrintf("Result value must not be null for property: %" PRId32, propId);
283 ASSERT_EQ(getValueResult.value()->getInt32Values(), std::vector<int32_t>({setValue}))
284 << StringPrintf("Boolean value not updated after set for property: %" PRId32,
285 propId);
286 }
287 }
288}
289
290// Test set() on an read_only property.
291TEST_P(VtsHalAutomotiveVehicleTargetTest, setNotWritableProp) {
292 ALOGD("VtsHalAutomotiveVehicleTargetTest::setNotWritableProp");
293
294 int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700295 if (!checkIsSupported(propId)) {
296 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
297 }
298
Yu Shan726d51a2022-02-22 17:37:21 -0800299 auto getValueResult = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
300 ASSERT_TRUE(getValueResult.ok())
301 << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s", propId,
302 getValueResult.error().message().c_str());
303
304 auto setValueResult = mVhalClient->setValueSync(*getValueResult.value());
305
306 ASSERT_FALSE(setValueResult.ok()) << "Expect set a read-only value to fail";
Yu Shan24fee7b2022-03-03 15:10:51 -0800307 ASSERT_EQ(setValueResult.error().code(), StatusCode::ACCESS_DENIED);
Yu Shan726d51a2022-02-22 17:37:21 -0800308}
309
310// Test subscribe() and unsubscribe().
311TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeAndUnsubscribe) {
312 ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeAndUnsubscribe");
313
314 int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700315 if (!checkIsSupported(propId)) {
316 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
317 }
Yu Shan726d51a2022-02-22 17:37:21 -0800318
Yu Shan4569ef52022-03-18 14:34:25 -0700319 auto propConfigsResult = mVhalClient->getPropConfigs({propId});
320
321 ASSERT_TRUE(propConfigsResult.ok()) << "Failed to get property config for PERF_VEHICLE_SPEED: "
322 << "error: " << propConfigsResult.error().message();
323 ASSERT_EQ(propConfigsResult.value().size(), 1u)
324 << "Expect to return 1 config for PERF_VEHICLE_SPEED";
325 auto& propConfig = propConfigsResult.value()[0];
326 float minSampleRate = propConfig->getMinSampleRate();
327 float maxSampleRate = propConfig->getMaxSampleRate();
328
329 if (minSampleRate < 1) {
330 GTEST_SKIP() << "Sample rate for vehicle speed < 1 times/sec, skip test since it would "
331 "take too long";
332 }
Yu Shan726d51a2022-02-22 17:37:21 -0800333
334 auto client = mVhalClient->getSubscriptionClient(mCallback);
335 ASSERT_NE(client, nullptr) << "Failed to get subscription client";
336
Yu Shan4569ef52022-03-18 14:34:25 -0700337 auto result = client->subscribe({{.propId = propId, .sampleRate = minSampleRate}});
Yu Shan726d51a2022-02-22 17:37:21 -0800338
339 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to subscribe to property: %" PRId32
340 ", error: %s",
341 propId, result.error().message().c_str());
Yu Shan4569ef52022-03-18 14:34:25 -0700342
343 if (mVhalClient->isAidlVhal()) {
344 // Skip checking timestamp for HIDL because the behavior for sample rate and timestamp is
345 // only specified clearly for AIDL.
346
347 // Timeout is 2 seconds, which gives a 1 second buffer.
348 ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, std::floor(minSampleRate),
349 std::chrono::seconds(2)))
350 << "Didn't get enough events for subscribing to minSampleRate";
351 }
352
353 result = client->subscribe({{.propId = propId, .sampleRate = maxSampleRate}});
354
355 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to subscribe to property: %" PRId32
356 ", error: %s",
357 propId, result.error().message().c_str());
358
359 if (mVhalClient->isAidlVhal()) {
360 ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, std::floor(maxSampleRate),
361 std::chrono::seconds(2)))
362 << "Didn't get enough events for subscribing to maxSampleRate";
363
364 std::unordered_set<int64_t> timestamps;
365 // Event event should have a different timestamp.
366 for (const int64_t& eventTimestamp : mCallback->getEventTimestamps(propId)) {
367 ASSERT_TRUE(timestamps.find(eventTimestamp) == timestamps.end())
368 << "two events for the same property must not have the same timestamp";
369 timestamps.insert(eventTimestamp);
370 }
371 }
Yu Shan726d51a2022-02-22 17:37:21 -0800372
373 result = client->unsubscribe({propId});
374 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to unsubscribe to property: %" PRId32
375 ", error: %s",
376 propId, result.error().message().c_str());
377
378 mCallback->reset();
379 ASSERT_FALSE(mCallback->waitForExpectedEvents(propId, 10, std::chrono::seconds(1)))
380 << "Expect not to get events after unsubscription";
381}
382
383// Test subscribe() with an invalid property.
384TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeInvalidProp) {
385 ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeInvalidProp");
386
387 std::vector<SubscribeOptions> options = {
388 SubscribeOptions{.propId = kInvalidProp, .sampleRate = 10.0}};
389
390 auto client = mVhalClient->getSubscriptionClient(mCallback);
391 ASSERT_NE(client, nullptr) << "Failed to get subscription client";
392
393 auto result = client->subscribe(options);
394
395 ASSERT_FALSE(result.ok()) << StringPrintf("Expect subscribing to property: %" PRId32 " to fail",
396 kInvalidProp);
397}
398
Yu Shan4569ef52022-03-18 14:34:25 -0700399// Test the timestamp returned in GetValues results is the timestamp when the value is retrieved.
400TEST_P(VtsHalAutomotiveVehicleTargetTest, testGetValuesTimestampAIDL) {
401 if (!mVhalClient->isAidlVhal()) {
402 GTEST_SKIP() << "Skip checking timestamp for HIDL because the behavior is only specified "
403 "for AIDL";
404 }
405
406 int32_t propId = toInt(VehicleProperty::PARKING_BRAKE_ON);
Yu Shanda7a4dd2023-10-09 14:43:36 -0700407 if (!checkIsSupported(propId)) {
408 GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
409 }
Yu Shan4569ef52022-03-18 14:34:25 -0700410 auto prop = mVhalClient->createHalPropValue(propId);
411
412 auto result = mVhalClient->getValueSync(*prop);
413
414 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
415 ", error: %s",
416 propId, result.error().message().c_str());
417 ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
418 ASSERT_EQ(result.value()->getInt32Values().size(), 1u) << "Result must contain 1 int value";
419
420 bool parkBrakeOnValue1 = (result.value()->getInt32Values()[0] == 1);
421 int64_t timestampValue1 = result.value()->getTimestamp();
422
423 result = mVhalClient->getValueSync(*prop);
424
425 ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
426 ", error: %s",
427 propId, result.error().message().c_str());
428 ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
429 ASSERT_EQ(result.value()->getInt32Values().size(), 1u) << "Result must contain 1 int value";
430
431 bool parkBarkeOnValue2 = (result.value()->getInt32Values()[0] == 1);
432 int64_t timestampValue2 = result.value()->getTimestamp();
433
434 if (parkBarkeOnValue2 == parkBrakeOnValue1) {
435 ASSERT_EQ(timestampValue2, timestampValue1)
436 << "getValue result must contain a timestamp updated when the value was updated, if"
437 "the value does not change, expect the same timestamp";
438 } else {
439 ASSERT_GT(timestampValue2, timestampValue1)
440 << "getValue result must contain a timestamp updated when the value was updated, if"
441 "the value changes, expect the newer value has a larger timestamp";
442 }
443}
444
Yu Shanda7a4dd2023-10-09 14:43:36 -0700445bool VtsHalAutomotiveVehicleTargetTest::checkIsSupported(int32_t propertyId) {
446 auto result = mVhalClient->getPropConfigs({propertyId});
447 return result.ok();
448}
449
Yu Shan726d51a2022-02-22 17:37:21 -0800450std::vector<ServiceDescriptor> getDescriptors() {
451 std::vector<ServiceDescriptor> descriptors;
452 for (std::string name : getAidlHalInstanceNames(IVehicle::descriptor)) {
453 descriptors.push_back({
454 .name = name,
455 .isAidlService = true,
456 });
457 }
Yu Shan928062c2024-01-25 17:40:41 -0800458 for (std::string name : getAllHalInstanceNames(
459 android::hardware::automotive::vehicle::V2_0::IVehicle::descriptor)) {
Yu Shan726d51a2022-02-22 17:37:21 -0800460 descriptors.push_back({
461 .name = name,
462 .isAidlService = false,
463 });
464 }
465 return descriptors;
466}
467
468GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VtsHalAutomotiveVehicleTargetTest);
469
470INSTANTIATE_TEST_SUITE_P(PerInstance, VtsHalAutomotiveVehicleTargetTest,
471 testing::ValuesIn(getDescriptors()),
472 [](const testing::TestParamInfo<ServiceDescriptor>& info) {
473 std::string name = "";
474 if (info.param.isAidlService) {
475 name += "aidl_";
476 } else {
477 name += "hidl_";
478 }
479 name += info.param.name;
480 return Sanitize(name);
481 });
482
483int main(int argc, char** argv) {
484 ::testing::InitGoogleTest(&argc, argv);
485 ABinderProcess_setThreadPoolMaxThreadCount(1);
486 return RUN_ALL_TESTS();
487}