1 /*
2 * Copyright (C) 2021 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 "DefaultVehicleHal"
18 #define ATRACE_TAG ATRACE_TAG_HAL
19
20 #include <DefaultVehicleHal.h>
21
22 #include <LargeParcelableBase.h>
23 #include <VehicleHalTypes.h>
24 #include <VehicleUtils.h>
25 #include <VersionForVehicleProperty.h>
26
27 #include <android-base/logging.h>
28 #include <android-base/result.h>
29 #include <android-base/stringprintf.h>
30 #include <android/binder_ibinder.h>
31 #include <private/android_filesystem_config.h>
32 #include <utils/Log.h>
33 #include <utils/SystemClock.h>
34 #include <utils/Trace.h>
35
36 #include <inttypes.h>
37 #include <chrono>
38 #include <set>
39 #include <unordered_set>
40
41 namespace android {
42 namespace hardware {
43 namespace automotive {
44 namespace vehicle {
45
46 namespace {
47
48 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
49 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
50 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
51 using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
52 using ::aidl::android::hardware::automotive::vehicle::HasSupportedValueInfo;
53 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
54 using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult;
55 using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResults;
56 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
57 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
58 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
59 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
60 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
61 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
62 using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResult;
63 using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResults;
64 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
65 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
66 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
67 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
68 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
69 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
70 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
71 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
72 using ::aidl::android::hardware::automotive::vehicle::VersionForVehicleProperty;
73 using ::android::automotive::car_binder_lib::LargeParcelableBase;
74 using ::android::base::Error;
75 using ::android::base::expected;
76 using ::android::base::Result;
77 using ::android::base::StringPrintf;
78
79 using ::ndk::ScopedAIBinder_DeathRecipient;
80 using ::ndk::ScopedAStatus;
81 using ::ndk::ScopedFileDescriptor;
82
83 using VhalPropIdAreaId = ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;
84
toString(const std::unordered_set<int64_t> & values)85 std::string toString(const std::unordered_set<int64_t>& values) {
86 std::string str = "";
87 for (auto it = values.begin(); it != values.end(); it++) {
88 str += std::to_string(*it);
89 if (std::next(it, 1) != values.end()) {
90 str += ", ";
91 }
92 }
93 return str;
94 }
95
getDefaultSampleRateHz(float sampleRateHz,float minSampleRateHz,float maxSampleRateHz)96 float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) {
97 if (sampleRateHz < minSampleRateHz) {
98 return minSampleRateHz;
99 }
100 if (sampleRateHz > maxSampleRateHz) {
101 return maxSampleRateHz;
102 }
103 return sampleRateHz;
104 }
105
106 class SCOPED_CAPABILITY SharedScopedLockAssertion {
107 public:
ACQUIRE_SHARED(mutex)108 SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {}
RELEASE()109 ~SharedScopedLockAssertion() RELEASE() {}
110 };
111
112 class SCOPED_CAPABILITY UniqueScopedLockAssertion {
113 public:
ACQUIRE(mutex)114 UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {}
RELEASE()115 ~UniqueScopedLockAssertion() RELEASE() {}
116 };
117
118 } // namespace
119
DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)120 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
121 : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0) {};
122
DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,int32_t testInterfaceVersion)123 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
124 int32_t testInterfaceVersion)
125 : mVehicleHardware(std::move(vehicleHardware)),
126 mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
127 mTestInterfaceVersion(testInterfaceVersion) {
128 ALOGD("DefaultVehicleHal init");
129 IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
130 mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
131 mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
132 if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
133 mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
134 mPropertyChangeEventsBatchingConsumer =
135 std::make_shared<BatchingConsumer<VehiclePropValue>>();
136 mPropertyChangeEventsBatchingConsumer->run(
137 mBatchedEventQueue.get(), mEventBatchingWindow,
138 [this](std::vector<VehiclePropValue> batchedEvents) {
139 handleBatchedPropertyEvents(std::move(batchedEvents));
140 });
141 }
142
143 std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
144 std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
145 std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
146 mVehicleHardware->registerOnPropertyChangeEvent(
147 std::make_unique<IVehicleHardware::PropertyChangeCallback>(
148 [subscriptionManagerCopy, batchedEventQueueCopy,
149 eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
150 if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
151 batchPropertyChangeEvent(batchedEventQueueCopy,
152 std::move(updatedValues));
153 } else {
154 onPropertyChangeEvent(subscriptionManagerCopy,
155 std::move(updatedValues));
156 }
157 }));
158 mVehicleHardware->registerOnPropertySetErrorEvent(
159 std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
160 [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
161 onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
162 }));
163 mVehicleHardware->registerSupportedValueChangeCallback(
164 std::make_unique<IVehicleHardware::SupportedValueChangeCallback>(
165 [subscriptionManagerCopy](std::vector<PropIdAreaId> propIdAreaIds) {
166 onSupportedValueChange(subscriptionManagerCopy, propIdAreaIds);
167 }));
168
169 // Register heartbeat event.
170 mRecurrentAction = std::make_shared<std::function<void()>>(
171 [vehicleHardwarePtr, subscriptionManagerCopy]() {
172 checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
173 });
174 mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
175
176 mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
177 mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
178 mDeathRecipient = ScopedAIBinder_DeathRecipient(
179 AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
180 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
181 &DefaultVehicleHal::onBinderUnlinked);
182 }
183
~DefaultVehicleHal()184 DefaultVehicleHal::~DefaultVehicleHal() {
185 // Delete the deathRecipient so that onBinderDied would not be called to reference 'this'.
186 mDeathRecipient = ScopedAIBinder_DeathRecipient();
187 mBinderEvents.deactivate();
188 if (mOnBinderDiedUnlinkedHandlerThread.joinable()) {
189 mOnBinderDiedUnlinkedHandlerThread.join();
190 }
191 // mRecurrentAction uses pointer to mVehicleHardware, so it has to be unregistered before
192 // mVehicleHardware.
193 mRecurrentTimer.unregisterTimerCallback(mRecurrentAction);
194
195 if (mBatchedEventQueue) {
196 // mPropertyChangeEventsBatchingConsumer uses mSubscriptionManager and mBatchedEventQueue.
197 mBatchedEventQueue->deactivate();
198 mPropertyChangeEventsBatchingConsumer->requestStop();
199 mPropertyChangeEventsBatchingConsumer->waitStopped();
200 mPropertyChangeEventsBatchingConsumer.reset();
201 mBatchedEventQueue.reset();
202 }
203
204 // mSubscriptionManager uses pointer to mVehicleHardware, so it has to be destroyed before
205 // mVehicleHardware.
206 mSubscriptionManager.reset();
207 mVehicleHardware.reset();
208 }
209
batchPropertyChangeEvent(const std::weak_ptr<ConcurrentQueue<VehiclePropValue>> & batchedEventQueue,std::vector<VehiclePropValue> && updatedValues)210 void DefaultVehicleHal::batchPropertyChangeEvent(
211 const std::weak_ptr<ConcurrentQueue<VehiclePropValue>>& batchedEventQueue,
212 std::vector<VehiclePropValue>&& updatedValues) {
213 auto batchedEventQueueStrong = batchedEventQueue.lock();
214 if (batchedEventQueueStrong == nullptr) {
215 ALOGW("%s: the batched property events queue is destroyed, DefaultVehicleHal is ending",
216 __func__);
217 return;
218 }
219 batchedEventQueueStrong->push(std::move(updatedValues));
220 }
221
handleBatchedPropertyEvents(std::vector<VehiclePropValue> && batchedEvents)222 void DefaultVehicleHal::handleBatchedPropertyEvents(std::vector<VehiclePropValue>&& batchedEvents) {
223 onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents));
224 }
225
onPropertyChangeEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,std::vector<VehiclePropValue> && updatedValues)226 void DefaultVehicleHal::onPropertyChangeEvent(
227 const std::weak_ptr<SubscriptionManager>& subscriptionManager,
228 std::vector<VehiclePropValue>&& updatedValues) {
229 ATRACE_CALL();
230 auto manager = subscriptionManager.lock();
231 if (manager == nullptr) {
232 ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
233 return;
234 }
235 auto updatedValuesByClients = manager->getSubscribedClients(std::move(updatedValues));
236 for (auto& [callback, values] : updatedValuesByClients) {
237 SubscriptionClient::sendUpdatedValues(callback, std::move(values));
238 }
239 }
240
onPropertySetErrorEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,const std::vector<SetValueErrorEvent> & errorEvents)241 void DefaultVehicleHal::onPropertySetErrorEvent(
242 const std::weak_ptr<SubscriptionManager>& subscriptionManager,
243 const std::vector<SetValueErrorEvent>& errorEvents) {
244 auto manager = subscriptionManager.lock();
245 if (manager == nullptr) {
246 ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
247 return;
248 }
249 auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents);
250 for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) {
251 SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors));
252 }
253 }
254
onSupportedValueChange(const std::weak_ptr<SubscriptionManager> & subscriptionManager,const std::vector<PropIdAreaId> & propIdAreaIds)255 void DefaultVehicleHal::onSupportedValueChange(
256 const std::weak_ptr<SubscriptionManager>& subscriptionManager,
257 const std::vector<PropIdAreaId>& propIdAreaIds) {
258 auto manager = subscriptionManager.lock();
259 if (manager == nullptr) {
260 ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
261 return;
262 }
263 auto updatedPropIdAreaIdsByClient =
264 manager->getSubscribedClientsForSupportedValueChange(propIdAreaIds);
265 for (auto& [callback, updatedPropIdAreaIds] : updatedPropIdAreaIdsByClient) {
266 SubscriptionClient::sendSupportedValueChangeEvents(callback, updatedPropIdAreaIds);
267 }
268 }
269
270 template <class T>
getOrCreateClient(std::unordered_map<const AIBinder *,std::shared_ptr<T>> * clients,const CallbackType & callback,std::shared_ptr<PendingRequestPool> pendingRequestPool)271 std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
272 std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
273 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
274 const AIBinder* clientId = callback->asBinder().get();
275 if (clients->find(clientId) == clients->end()) {
276 (*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
277 }
278 return (*clients)[clientId];
279 }
280
monitorBinderLifeCycleLocked(const AIBinder * clientId)281 bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) {
282 OnBinderDiedContext* contextPtr = nullptr;
283 if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
284 return mBinderLifecycleHandler->isAlive(clientId);
285 } else {
286 std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
287 OnBinderDiedContext{.vhal = this, .clientId = clientId});
288 // We know context must be alive when we use contextPtr because context would only
289 // be removed in OnBinderUnlinked, which must be called after OnBinderDied.
290 contextPtr = context.get();
291 // Insert into a map to keep the context object alive.
292 mOnBinderDiedContexts[clientId] = std::move(context);
293 }
294
295 // If this function fails, onBinderUnlinked would be called to remove the added context.
296 binder_status_t status = mBinderLifecycleHandler->linkToDeath(
297 const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
298 if (status == STATUS_OK) {
299 return true;
300 }
301 ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
302 static_cast<int>(status));
303 return false;
304 }
305
onBinderDied(void * cookie)306 void DefaultVehicleHal::onBinderDied(void* cookie) {
307 OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
308 // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
309 // thread because we might be holding the mLock the handler requires.
310 context->vhal->mBinderEvents.push(
311 BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId});
312 }
313
onBinderDiedWithContext(const AIBinder * clientId)314 void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) {
315 std::scoped_lock<std::mutex> lockGuard(mLock);
316 ALOGD("binder died, client ID: %p", clientId);
317 mSetValuesClients.erase(clientId);
318 mGetValuesClients.erase(clientId);
319 mSubscriptionManager->unsubscribe(clientId);
320 }
321
onBinderUnlinked(void * cookie)322 void DefaultVehicleHal::onBinderUnlinked(void* cookie) {
323 OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
324 // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
325 // thread because we might be holding the mLock the handler requires.
326 context->vhal->mBinderEvents.push(
327 BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId});
328 }
329
onBinderUnlinkedWithContext(const AIBinder * clientId)330 void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) {
331 ALOGD("binder unlinked");
332 std::scoped_lock<std::mutex> lockGuard(mLock);
333 // Delete the context associated with this cookie.
334 mOnBinderDiedContexts.erase(clientId);
335 }
336
onBinderDiedUnlinkedHandler()337 void DefaultVehicleHal::onBinderDiedUnlinkedHandler() {
338 while (mBinderEvents.waitForItems()) {
339 for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) {
340 if (event.forOnBinderDied) {
341 onBinderDiedWithContext(event.clientId);
342 } else {
343 onBinderUnlinkedWithContext(event.clientId);
344 }
345 }
346 }
347 }
348
349 template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
350 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
351 std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
352 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
353 template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
354 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
355 std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
356 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
357
setTimeout(int64_t timeoutInNano)358 void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
359 mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
360 }
361
getVhalInterfaceVersion() const362 int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
363 if (mTestInterfaceVersion != 0) {
364 return mTestInterfaceVersion;
365 }
366 int32_t myVersion = 0;
367 // getInterfaceVersion is in-reality a const method.
368 const_cast<DefaultVehicleHal*>(this)->getInterfaceVersion(&myVersion);
369 return myVersion;
370 }
371
isConfigSupportedForCurrentVhalVersion(const VehiclePropConfig & config) const372 bool DefaultVehicleHal::isConfigSupportedForCurrentVhalVersion(
373 const VehiclePropConfig& config) const {
374 int32_t myVersion = getVhalInterfaceVersion();
375 if (!isSystemProp(config.prop)) {
376 return true;
377 }
378 VehicleProperty property = static_cast<VehicleProperty>(config.prop);
379 std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
380 auto it = VersionForVehicleProperty.find(property);
381 if (it == VersionForVehicleProperty.end()) {
382 ALOGE("The property: %s is not a supported system property, ignore", propertyName.c_str());
383 return false;
384 }
385 int requiredVersion = it->second;
386 if (myVersion < requiredVersion) {
387 ALOGE("The property: %s is not supported for current client VHAL version, "
388 "require %d, current version: %d, ignore",
389 propertyName.c_str(), requiredVersion, myVersion);
390 return false;
391 }
392 return true;
393 }
394
getAllPropConfigsFromHardwareLocked() const395 bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
396 ALOGD("Get all property configs from hardware");
397 auto configs = mVehicleHardware->getAllPropertyConfigs();
398 std::vector<VehiclePropConfig> filteredConfigs;
399 for (const auto& config : configs) {
400 if (isConfigSupportedForCurrentVhalVersion(config)) {
401 filteredConfigs.push_back(std::move(config));
402 }
403 }
404
405 {
406 std::unique_lock<std::shared_timed_mutex> configWriteLock(mConfigLock);
407 UniqueScopedLockAssertion lockAssertion(mConfigLock);
408
409 for (auto& config : filteredConfigs) {
410 mConfigsByPropId[config.prop] = config;
411 }
412 VehiclePropConfigs vehiclePropConfigs;
413 vehiclePropConfigs.payloads = std::move(filteredConfigs);
414 auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
415 if (!result.ok()) {
416 ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
417 result.error().message().c_str(), static_cast<int>(result.error().code()));
418 mConfigFile = nullptr;
419 return false;
420 }
421
422 if (result.value() != nullptr) {
423 mConfigFile = std::move(result.value());
424 }
425 }
426
427 mConfigInit = true;
428 return true;
429 }
430
getConfigsByPropId(std::function<void (const std::unordered_map<int32_t,VehiclePropConfig> &)> callback) const431 void DefaultVehicleHal::getConfigsByPropId(
432 std::function<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
433 if (!mConfigInit) {
434 CHECK(getAllPropConfigsFromHardwareLocked())
435 << "Failed to get property configs from hardware";
436 }
437
438 std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
439 SharedScopedLockAssertion lockAssertion(mConfigLock);
440
441 callback(mConfigsByPropId);
442 }
443
getAllPropConfigs(VehiclePropConfigs * output)444 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
445 if (!mConfigInit) {
446 CHECK(getAllPropConfigsFromHardwareLocked())
447 << "Failed to get property configs from hardware";
448 }
449
450 std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
451 SharedScopedLockAssertion lockAssertion(mConfigLock);
452
453 if (mConfigFile != nullptr) {
454 output->payloads.clear();
455 output->sharedMemoryFd.set(dup(mConfigFile->get()));
456 return ScopedAStatus::ok();
457 }
458
459 output->payloads.reserve(mConfigsByPropId.size());
460 for (const auto& [_, config] : mConfigsByPropId) {
461 output->payloads.push_back(config);
462 }
463 return ScopedAStatus::ok();
464 }
465
getConfig(int32_t propId) const466 Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
467 Result<VehiclePropConfig> result;
468
469 if (!mConfigInit) {
470 std::optional<VehiclePropConfig> config = mVehicleHardware->getPropertyConfig(propId);
471 if (!config.has_value()) {
472 return Error() << "no config for property, ID: " << propId;
473 }
474 if (!isConfigSupportedForCurrentVhalVersion(config.value())) {
475 return Error() << "property not supported for current VHAL interface, ID: " << propId;
476 }
477
478 return config.value();
479 }
480
481 getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
482 SharedScopedLockAssertion lockAssertion(mConfigLock);
483
484 auto it = configsByPropId.find(propId);
485 if (it == configsByPropId.end()) {
486 result = Error() << "no config for property, ID: " << propId;
487 return;
488 }
489 // Copy the VehiclePropConfig
490 result = it->second;
491 });
492 return result;
493 }
494
checkProperty(const VehiclePropValue & propValue)495 Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
496 int32_t propId = propValue.prop;
497 auto result = getConfig(propId);
498 if (!result.ok()) {
499 return result.error();
500 }
501 const VehiclePropConfig& config = result.value();
502 const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
503 if (!isGlobalProp(propId) && areaConfig == nullptr) {
504 // Ignore areaId for global property. For non global property, check whether areaId is
505 // allowed. areaId must appear in areaConfig.
506 return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
507 << ", not listed in config";
508 }
509 if (auto result = checkPropValue(propValue, &config); !result.ok()) {
510 return Error() << "invalid property value: " << propValue.toString()
511 << ", error: " << getErrorMsg(result);
512 }
513 if (auto result = checkValueRange(propValue, areaConfig); !result.ok()) {
514 return Error() << "property value out of range: " << propValue.toString()
515 << ", error: " << getErrorMsg(result);
516 }
517 return {};
518 }
519
getValues(const CallbackType & callback,const GetValueRequests & requests)520 ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
521 const GetValueRequests& requests) {
522 ATRACE_CALL();
523 if (callback == nullptr) {
524 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
525 }
526 expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
527 deserializedResults = fromStableLargeParcelable(requests);
528 if (!deserializedResults.ok()) {
529 ALOGE("getValues: failed to parse getValues requests");
530 return std::move(deserializedResults.error());
531 }
532 const std::vector<GetValueRequest>& getValueRequests =
533 deserializedResults.value().getObject()->payloads;
534
535 auto maybeRequestIds = checkDuplicateRequests(getValueRequests);
536 if (!maybeRequestIds.ok()) {
537 ALOGE("getValues: duplicate request ID");
538 return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
539 }
540
541 // A list of failed result we already know before sending to hardware.
542 std::vector<GetValueResult> failedResults;
543 // The list of requests that we would send to hardware.
544 std::vector<GetValueRequest> hardwareRequests;
545
546 for (const auto& request : getValueRequests) {
547 if (auto result = checkReadPermission(request.prop); !result.ok()) {
548 ALOGW("property does not support reading: %s", getErrorMsg(result).c_str());
549 failedResults.push_back(GetValueResult{
550 .requestId = request.requestId,
551 .status = getErrorCode(result),
552 .prop = {},
553 });
554 continue;
555 }
556 hardwareRequests.push_back(request);
557 }
558
559 // The set of request Ids that we would send to hardware.
560 std::unordered_set<int64_t> hardwareRequestIds;
561 for (const auto& request : hardwareRequests) {
562 hardwareRequestIds.insert(request.requestId);
563 }
564
565 std::shared_ptr<GetValuesClient> client;
566 {
567 // Lock to make sure onBinderDied would not be called concurrently.
568 std::scoped_lock lockGuard(mLock);
569 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
570 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
571 "client died");
572 }
573
574 client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
575 }
576
577 // Register the pending hardware requests and also check for duplicate request Ids.
578 if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
579 ALOGE("getValues[%s]: failed to add pending requests, error: %s",
580 toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
581 return toScopedAStatus(addRequestResult);
582 }
583
584 if (!failedResults.empty()) {
585 // First send the failed results we already know back to the client.
586 client->sendResults(std::move(failedResults));
587 }
588
589 if (hardwareRequests.empty()) {
590 return ScopedAStatus::ok();
591 }
592
593 if (StatusCode status =
594 mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests);
595 status != StatusCode::OK) {
596 // If the hardware returns error, finish all the pending requests for this request because
597 // we never expect hardware to call callback for these requests.
598 client->tryFinishRequests(hardwareRequestIds);
599 ALOGE("getValues[%s]: failed to get value from VehicleHardware, status: %d",
600 toString(hardwareRequestIds).c_str(), toInt(status));
601 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
602 toInt(status), "failed to get value from VehicleHardware");
603 }
604 return ScopedAStatus::ok();
605 }
606
setValues(const CallbackType & callback,const SetValueRequests & requests)607 ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
608 const SetValueRequests& requests) {
609 ATRACE_CALL();
610 if (callback == nullptr) {
611 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
612 }
613 expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
614 deserializedResults = fromStableLargeParcelable(requests);
615 if (!deserializedResults.ok()) {
616 ALOGE("setValues: failed to parse setValues requests");
617 return std::move(deserializedResults.error());
618 }
619 const std::vector<SetValueRequest>& setValueRequests =
620 deserializedResults.value().getObject()->payloads;
621
622 // A list of failed result we already know before sending to hardware.
623 std::vector<SetValueResult> failedResults;
624 // The list of requests that we would send to hardware.
625 std::vector<SetValueRequest> hardwareRequests;
626
627 auto maybeRequestIds = checkDuplicateRequests(setValueRequests);
628 if (!maybeRequestIds.ok()) {
629 ALOGE("setValues: duplicate request ID");
630 return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
631 }
632
633 for (auto& request : setValueRequests) {
634 int64_t requestId = request.requestId;
635 if (auto result = checkWritePermission(request.value); !result.ok()) {
636 ALOGW("property does not support writing: %s", getErrorMsg(result).c_str());
637 failedResults.push_back(SetValueResult{
638 .requestId = requestId,
639 .status = getErrorCode(result),
640 });
641 continue;
642 }
643 if (auto result = checkProperty(request.value); !result.ok()) {
644 ALOGW("setValues[%" PRId64 "]: property is not valid: %s", requestId,
645 getErrorMsg(result).c_str());
646 failedResults.push_back(SetValueResult{
647 .requestId = requestId,
648 .status = StatusCode::INVALID_ARG,
649 });
650 continue;
651 }
652
653 hardwareRequests.push_back(request);
654 }
655
656 // The set of request Ids that we would send to hardware.
657 std::unordered_set<int64_t> hardwareRequestIds;
658 for (const auto& request : hardwareRequests) {
659 hardwareRequestIds.insert(request.requestId);
660 }
661
662 std::shared_ptr<SetValuesClient> client;
663 {
664 // Lock to make sure onBinderDied would not be called concurrently.
665 std::scoped_lock lockGuard(mLock);
666 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
667 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
668 "client died");
669 }
670 client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
671 }
672
673 // Register the pending hardware requests and also check for duplicate request Ids.
674 if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
675 ALOGE("setValues[%s], failed to add pending requests, error: %s",
676 toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
677 return toScopedAStatus(addRequestResult);
678 }
679
680 if (!failedResults.empty()) {
681 // First send the failed results we already know back to the client.
682 client->sendResults(std::move(failedResults));
683 }
684
685 if (hardwareRequests.empty()) {
686 return ScopedAStatus::ok();
687 }
688
689 if (StatusCode status =
690 mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
691 status != StatusCode::OK) {
692 // If the hardware returns error, finish all the pending requests for this request because
693 // we never expect hardware to call callback for these requests.
694 client->tryFinishRequests(hardwareRequestIds);
695 ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d",
696 toString(hardwareRequestIds).c_str(), toInt(status));
697 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
698 toInt(status), "failed to set value to VehicleHardware");
699 }
700
701 return ScopedAStatus::ok();
702 }
703
704 #define CHECK_DUPLICATE_REQUESTS(PROP_NAME) \
705 do { \
706 std::vector<int64_t> requestIds; \
707 std::set<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> requestProps; \
708 for (const auto& request : requests) { \
709 const auto& prop = request.PROP_NAME; \
710 if (requestProps.count(prop) != 0) { \
711 return ::android::base::Error() \
712 << "duplicate request for property: " << prop.toString(); \
713 } \
714 requestProps.insert(prop); \
715 requestIds.push_back(request.requestId); \
716 } \
717 return requestIds; \
718 } while (0);
719
checkDuplicateRequests(const std::vector<GetValueRequest> & requests)720 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
721 const std::vector<GetValueRequest>& requests) {
722 CHECK_DUPLICATE_REQUESTS(prop);
723 }
724
checkDuplicateRequests(const std::vector<SetValueRequest> & requests)725 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
726 const std::vector<SetValueRequest>& requests) {
727 CHECK_DUPLICATE_REQUESTS(value);
728 }
729
730 #undef CHECK_DUPLICATE_REQUESTS
731
getPropConfigs(const std::vector<int32_t> & props,VehiclePropConfigs * output)732 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
733 VehiclePropConfigs* output) {
734 std::vector<VehiclePropConfig> configs;
735
736 if (!mConfigInit) {
737 for (int32_t prop : props) {
738 auto maybeConfig = mVehicleHardware->getPropertyConfig(prop);
739 if (!maybeConfig.has_value() ||
740 !isConfigSupportedForCurrentVhalVersion(maybeConfig.value())) {
741 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
742 toInt(StatusCode::INVALID_ARG),
743 StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
744 }
745 configs.push_back(maybeConfig.value());
746 }
747
748 return vectorToStableLargeParcelable(std::move(configs), output);
749 }
750
751 ScopedAStatus status = ScopedAStatus::ok();
752 getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
753 SharedScopedLockAssertion lockAssertion(mConfigLock);
754
755 for (int32_t prop : props) {
756 auto it = configsByPropId.find(prop);
757 if (it != configsByPropId.end()) {
758 configs.push_back(it->second);
759 } else {
760 status = ScopedAStatus::fromServiceSpecificErrorWithMessage(
761 toInt(StatusCode::INVALID_ARG),
762 StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
763 return;
764 }
765 }
766 });
767
768 if (!status.isOk()) {
769 return status;
770 }
771
772 return vectorToStableLargeParcelable(std::move(configs), output);
773 }
774
hasRequiredAccess(VehiclePropertyAccess access,VehiclePropertyAccess requiredAccess)775 bool hasRequiredAccess(VehiclePropertyAccess access, VehiclePropertyAccess requiredAccess) {
776 return access == requiredAccess || access == VehiclePropertyAccess::READ_WRITE;
777 }
778
areaConfigsHaveRequiredAccess(const std::vector<VehicleAreaConfig> & areaConfigs,VehiclePropertyAccess requiredAccess)779 bool areaConfigsHaveRequiredAccess(const std::vector<VehicleAreaConfig>& areaConfigs,
780 VehiclePropertyAccess requiredAccess) {
781 if (areaConfigs.empty()) {
782 return false;
783 }
784 for (VehicleAreaConfig areaConfig : areaConfigs) {
785 if (!hasRequiredAccess(areaConfig.access, requiredAccess)) {
786 return false;
787 }
788 }
789 return true;
790 }
791
checkSubscribeOptions(const std::vector<SubscribeOptions> & options,const std::unordered_map<int32_t,VehiclePropConfig> & configsByPropId)792 VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
793 const std::vector<SubscribeOptions>& options,
794 const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId) {
795 for (const auto& option : options) {
796 int32_t propId = option.propId;
797 auto it = configsByPropId.find(propId);
798 if (it == configsByPropId.end()) {
799 return StatusError(StatusCode::INVALID_ARG)
800 << StringPrintf("no config for property, ID: %" PRId32, propId);
801 }
802 const VehiclePropConfig& config = it->second;
803 std::vector<VehicleAreaConfig> areaConfigs;
804 if (option.areaIds.empty()) {
805 areaConfigs = config.areaConfigs;
806 } else {
807 std::unordered_map<int, VehicleAreaConfig> areaConfigByAreaId;
808 for (const VehicleAreaConfig& areaConfig : config.areaConfigs) {
809 areaConfigByAreaId.emplace(areaConfig.areaId, areaConfig);
810 }
811 for (int areaId : option.areaIds) {
812 auto it = areaConfigByAreaId.find(areaId);
813 if (it != areaConfigByAreaId.end()) {
814 areaConfigs.push_back(it->second);
815 } else if (areaId != 0 || !areaConfigByAreaId.empty()) {
816 return StatusError(StatusCode::INVALID_ARG)
817 << StringPrintf("invalid area ID: %" PRId32 " for prop ID: %" PRId32
818 ", not listed in config",
819 areaId, propId);
820 }
821 }
822 }
823
824 if (config.changeMode != VehiclePropertyChangeMode::ON_CHANGE &&
825 config.changeMode != VehiclePropertyChangeMode::CONTINUOUS) {
826 return StatusError(StatusCode::INVALID_ARG)
827 << "only support subscribing to ON_CHANGE or CONTINUOUS property";
828 }
829
830 // Either VehiclePropConfig.access or VehicleAreaConfig.access will be specified
831 if (!hasRequiredAccess(config.access, VehiclePropertyAccess::READ) &&
832 !areaConfigsHaveRequiredAccess(areaConfigs, VehiclePropertyAccess::READ)) {
833 return StatusError(StatusCode::ACCESS_DENIED)
834 << StringPrintf("Property %" PRId32 " has no read access", propId);
835 }
836
837 if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
838 float sampleRateHz = option.sampleRate;
839 float minSampleRateHz = config.minSampleRate;
840 float maxSampleRateHz = config.maxSampleRate;
841 float defaultRateHz =
842 getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz);
843 if (sampleRateHz != defaultRateHz) {
844 ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f "
845 "HZ",
846 sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz);
847 sampleRateHz = defaultRateHz;
848 }
849 if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) {
850 return StatusError(StatusCode::INVALID_ARG)
851 << "invalid sample rate: " << sampleRateHz << " HZ";
852 }
853 if (!SubscriptionManager::checkResolution(option.resolution)) {
854 return StatusError(StatusCode::INVALID_ARG)
855 << "invalid resolution: " << option.resolution;
856 }
857 }
858 }
859
860 return {};
861 }
862
parseSubscribeOptions(const std::vector<SubscribeOptions> & options,const std::unordered_map<int32_t,VehiclePropConfig> & configsByPropId,std::vector<SubscribeOptions> & onChangeSubscriptions,std::vector<SubscribeOptions> & continuousSubscriptions)863 void DefaultVehicleHal::parseSubscribeOptions(
864 const std::vector<SubscribeOptions>& options,
865 const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
866 std::vector<SubscribeOptions>& onChangeSubscriptions,
867 std::vector<SubscribeOptions>& continuousSubscriptions) {
868 for (const auto& option : options) {
869 int32_t propId = option.propId;
870 // We have already validate config exists.
871 const VehiclePropConfig& config = configsByPropId.at(propId);
872
873 SubscribeOptions optionCopy = option;
874 // If areaIds is empty, subscribe to all areas.
875 if (optionCopy.areaIds.empty() && !isGlobalProp(propId)) {
876 for (const auto& areaConfig : config.areaConfigs) {
877 optionCopy.areaIds.push_back(areaConfig.areaId);
878 }
879 }
880
881 if (isGlobalProp(propId)) {
882 optionCopy.areaIds = {0};
883 }
884
885 if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
886 optionCopy.sampleRate = getDefaultSampleRateHz(
887 optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate);
888 if (!optionCopy.enableVariableUpdateRate) {
889 continuousSubscriptions.push_back(std::move(optionCopy));
890 } else {
891 // If clients enables to VUR, we need to check whether VUR is supported for the
892 // specific [propId, areaId] and overwrite the option to disable if not supported.
893 std::vector<int32_t> areasVurEnabled;
894 std::vector<int32_t> areasVurDisabled;
895 for (int32_t areaId : optionCopy.areaIds) {
896 const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
897 if (areaConfig == nullptr) {
898 areasVurDisabled.push_back(areaId);
899 continue;
900 }
901 if (!areaConfig->supportVariableUpdateRate) {
902 areasVurDisabled.push_back(areaId);
903 continue;
904 }
905 areasVurEnabled.push_back(areaId);
906 }
907 if (!areasVurEnabled.empty()) {
908 SubscribeOptions optionVurEnabled = optionCopy;
909 optionVurEnabled.areaIds = areasVurEnabled;
910 optionVurEnabled.enableVariableUpdateRate = true;
911 continuousSubscriptions.push_back(std::move(optionVurEnabled));
912 }
913
914 if (!areasVurDisabled.empty()) {
915 // We use optionCopy for areas with VUR disabled.
916 optionCopy.areaIds = areasVurDisabled;
917 optionCopy.enableVariableUpdateRate = false;
918 continuousSubscriptions.push_back(std::move(optionCopy));
919 }
920 }
921 } else {
922 onChangeSubscriptions.push_back(std::move(optionCopy));
923 }
924 }
925 }
926
subscribe(const CallbackType & callback,const std::vector<SubscribeOptions> & options,int32_t maxSharedMemoryFileCount)927 ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
928 const std::vector<SubscribeOptions>& options,
929 [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
930 // TODO(b/205189110): Use shared memory file count.
931 if (callback == nullptr) {
932 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
933 }
934 std::vector<SubscribeOptions> onChangeSubscriptions;
935 std::vector<SubscribeOptions> continuousSubscriptions;
936 ScopedAStatus returnStatus = ScopedAStatus::ok();
937 getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions,
938 &continuousSubscriptions](const auto& configsByPropId) {
939 SharedScopedLockAssertion lockAssertion(mConfigLock);
940
941 if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) {
942 ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
943 returnStatus = toScopedAStatus(result);
944 return;
945 }
946 parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions,
947 continuousSubscriptions);
948 });
949
950 if (!returnStatus.isOk()) {
951 return returnStatus;
952 }
953
954 {
955 // Lock to make sure onBinderDied would not be called concurrently
956 // (before subscribe). Without this, we may create a new subscription for an already dead
957 // client which will never be unsubscribed.
958 std::scoped_lock lockGuard(mLock);
959 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
960 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
961 "client died");
962 }
963
964 if (!onChangeSubscriptions.empty()) {
965 auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
966 /*isContinuousProperty=*/false);
967 if (!result.ok()) {
968 return toScopedAStatus(result);
969 }
970 }
971 if (!continuousSubscriptions.empty()) {
972 auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions,
973 /*isContinuousProperty=*/true);
974 if (!result.ok()) {
975 return toScopedAStatus(result);
976 }
977 }
978 }
979 return ScopedAStatus::ok();
980 }
981
unsubscribe(const CallbackType & callback,const std::vector<int32_t> & propIds)982 ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType& callback,
983 const std::vector<int32_t>& propIds) {
984 if (callback == nullptr) {
985 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
986 }
987 return toScopedAStatus(mSubscriptionManager->unsubscribe(callback->asBinder().get(), propIds));
988 }
989
returnSharedMemory(const CallbackType &,int64_t)990 ScopedAStatus DefaultVehicleHal::returnSharedMemory(const CallbackType&, int64_t) {
991 // TODO(b/200737967): implement this.
992 return ScopedAStatus::ok();
993 }
994
getAreaConfigForPropIdAreaId(int32_t propId,int32_t areaId) const995 Result<VehicleAreaConfig> DefaultVehicleHal::getAreaConfigForPropIdAreaId(int32_t propId,
996 int32_t areaId) const {
997 auto result = getConfig(propId);
998 if (!result.ok()) {
999 return Error() << "Failed to get property config for propertyId: " << propIdToString(propId)
1000 << ", error: " << result.error();
1001 }
1002 const VehiclePropConfig& config = result.value();
1003 const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
1004 if (areaConfig == nullptr) {
1005 return Error() << "AreaId config not found for propertyId: " << propIdToString(propId)
1006 << ", areaId: " << areaId;
1007 }
1008 return *areaConfig;
1009 }
1010
getHasSupportedValueInfo(int32_t propId,int32_t areaId) const1011 Result<HasSupportedValueInfo> DefaultVehicleHal::getHasSupportedValueInfo(int32_t propId,
1012 int32_t areaId) const {
1013 Result<VehicleAreaConfig> propIdAreaIdConfigResult =
1014 getAreaConfigForPropIdAreaId(propId, areaId);
1015 if (!isGlobalProp(propId) && !propIdAreaIdConfigResult.ok()) {
1016 // For global property, it is possible that no config exists.
1017 return Error() << propIdAreaIdConfigResult.error();
1018 }
1019 if (propIdAreaIdConfigResult.has_value()) {
1020 auto areaConfig = propIdAreaIdConfigResult.value();
1021 if (areaConfig.hasSupportedValueInfo.has_value()) {
1022 return areaConfig.hasSupportedValueInfo.value();
1023 }
1024 }
1025 return Error() << "property: " << propIdToString(propId) << ", areaId: " << areaId
1026 << " does not support this operation because hasSupportedValueInfo is null";
1027 }
1028
getSupportedValuesLists(const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds,SupportedValuesListResults * supportedValuesListResults)1029 ScopedAStatus DefaultVehicleHal::getSupportedValuesLists(
1030 const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
1031 SupportedValuesListResults* supportedValuesListResults) {
1032 std::vector<size_t> toHardwareRequestCounters;
1033 std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
1034 std::vector<SupportedValuesListResult> results;
1035 results.resize(vhalPropIdAreaIds.size());
1036 for (size_t requestCounter = 0; requestCounter < vhalPropIdAreaIds.size(); requestCounter++) {
1037 const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(requestCounter);
1038 int32_t propId = vhalPropIdAreaId.propId;
1039 int32_t areaId = vhalPropIdAreaId.areaId;
1040 auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
1041 if (!hasSupportedValueInfoResult.ok()) {
1042 ALOGE("getSupportedValuesLists: %s",
1043 hasSupportedValueInfoResult.error().message().c_str());
1044 results[requestCounter] = SupportedValuesListResult{
1045 .status = StatusCode::INVALID_ARG, .supportedValuesList = std::nullopt};
1046 continue;
1047 }
1048
1049 const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
1050 if (hasSupportedValueInfo.hasSupportedValuesList) {
1051 toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
1052 toHardwareRequestCounters.push_back(requestCounter);
1053 } else {
1054 results[requestCounter] = SupportedValuesListResult{
1055 .status = StatusCode::OK, .supportedValuesList = std::nullopt};
1056 continue;
1057 }
1058 }
1059 if (toHardwarePropIdAreaIds.size() != 0) {
1060 std::vector<SupportedValuesListResult> resultsFromHardware =
1061 mVehicleHardware->getSupportedValuesLists(toHardwarePropIdAreaIds);
1062 // It is guaranteed that toHardwarePropIdAreaIds, toHardwareRequestCounters,
1063 // resultsFromHardware have the same size.
1064 if (resultsFromHardware.size() != toHardwareRequestCounters.size()) {
1065 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
1066 toInt(StatusCode::INTERNAL_ERROR),
1067 fmt::format(
1068 "getSupportedValuesLists: Unexpected results size from IVehicleHardware"
1069 ", got: {}, expect: {}",
1070 resultsFromHardware.size(), toHardwareRequestCounters.size())
1071 .c_str());
1072 }
1073 for (size_t i = 0; i < toHardwareRequestCounters.size(); i++) {
1074 results[toHardwareRequestCounters[i]] = resultsFromHardware[i];
1075 }
1076 }
1077 ScopedAStatus status =
1078 vectorToStableLargeParcelable(std::move(results), supportedValuesListResults);
1079 if (!status.isOk()) {
1080 int statusCode = status.getServiceSpecificError();
1081 ALOGE("getSupportedValuesLists: failed to marshal result into large parcelable, error: "
1082 "%s, code: %d",
1083 status.getMessage(), statusCode);
1084 return status;
1085 }
1086 return ScopedAStatus::ok();
1087 }
1088
getMinMaxSupportedValue(const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds,MinMaxSupportedValueResults * minMaxSupportedValueResults)1089 ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(
1090 const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
1091 MinMaxSupportedValueResults* minMaxSupportedValueResults) {
1092 std::vector<size_t> toHardwareRequestCounters;
1093 std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
1094 std::vector<MinMaxSupportedValueResult> results;
1095 results.resize(vhalPropIdAreaIds.size());
1096 for (size_t requestCounter = 0; requestCounter < vhalPropIdAreaIds.size(); requestCounter++) {
1097 const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(requestCounter);
1098 int32_t propId = vhalPropIdAreaId.propId;
1099 int32_t areaId = vhalPropIdAreaId.areaId;
1100 auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
1101 if (!hasSupportedValueInfoResult.ok()) {
1102 ALOGE("getMinMaxSupportedValue: %s",
1103 hasSupportedValueInfoResult.error().message().c_str());
1104 results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::INVALID_ARG,
1105 .minSupportedValue = std::nullopt,
1106 .maxSupportedValue = std::nullopt};
1107 continue;
1108 }
1109
1110 const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
1111 if (hasSupportedValueInfo.hasMinSupportedValue ||
1112 hasSupportedValueInfo.hasMaxSupportedValue) {
1113 toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
1114 toHardwareRequestCounters.push_back(requestCounter);
1115 } else {
1116 results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::OK,
1117 .minSupportedValue = std::nullopt,
1118 .maxSupportedValue = std::nullopt};
1119 continue;
1120 }
1121 }
1122 if (toHardwarePropIdAreaIds.size() != 0) {
1123 std::vector<MinMaxSupportedValueResult> resultsFromHardware =
1124 mVehicleHardware->getMinMaxSupportedValues(toHardwarePropIdAreaIds);
1125 // It is guaranteed that toHardwarePropIdAreaIds, toHardwareRequestCounters,
1126 // resultsFromHardware have the same size.
1127 if (resultsFromHardware.size() != toHardwareRequestCounters.size()) {
1128 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
1129 toInt(StatusCode::INTERNAL_ERROR),
1130 fmt::format(
1131 "getMinMaxSupportedValue: Unexpected results size from IVehicleHardware"
1132 ", got: {}, expect: {}",
1133 resultsFromHardware.size(), toHardwareRequestCounters.size())
1134 .c_str());
1135 }
1136 for (size_t i = 0; i < toHardwareRequestCounters.size(); i++) {
1137 results[toHardwareRequestCounters[i]] = resultsFromHardware[i];
1138 }
1139 }
1140 ScopedAStatus status =
1141 vectorToStableLargeParcelable(std::move(results), minMaxSupportedValueResults);
1142 if (!status.isOk()) {
1143 int statusCode = status.getServiceSpecificError();
1144 ALOGE("getMinMaxSupportedValue: failed to marshal result into large parcelable, error: "
1145 "%s, code: %d",
1146 status.getMessage(), statusCode);
1147 return status;
1148 }
1149 return ScopedAStatus::ok();
1150 }
1151
registerSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback> & callback,const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds)1152 ScopedAStatus DefaultVehicleHal::registerSupportedValueChangeCallback(
1153 const std::shared_ptr<IVehicleCallback>& callback,
1154 const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
1155 std::vector<PropIdAreaId> propIdAreaIdsToSubscribe;
1156 for (size_t i = 0; i < vhalPropIdAreaIds.size(); i++) {
1157 const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(i);
1158 int32_t propId = vhalPropIdAreaId.propId;
1159 int32_t areaId = vhalPropIdAreaId.areaId;
1160 auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
1161 if (!hasSupportedValueInfoResult.ok()) {
1162 ALOGE("registerSupportedValueChangeCallback not supported: %s",
1163 hasSupportedValueInfoResult.error().message().c_str());
1164 return toScopedAStatus(hasSupportedValueInfoResult, StatusCode::INVALID_ARG);
1165 }
1166 const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
1167 if (!hasSupportedValueInfo.hasMinSupportedValue &&
1168 !hasSupportedValueInfo.hasMaxSupportedValue &&
1169 !hasSupportedValueInfo.hasSupportedValuesList) {
1170 ALOGW("registerSupportedValueChangeCallback: do nothing for property: %s, "
1171 "areaId: %" PRId32
1172 ", no min/max supported values or supported values list"
1173 " specified",
1174 propIdToString(propId).c_str(), areaId);
1175 continue;
1176 }
1177 propIdAreaIdsToSubscribe.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
1178 }
1179 if (propIdAreaIdsToSubscribe.empty()) {
1180 return ScopedAStatus::ok();
1181 }
1182 {
1183 // Lock to make sure onBinderDied would not be called concurrently
1184 // (before subscribeSupportedValueChange). Without this, we may create a new subscription
1185 // for an already dead client which will never be unsubscribed.
1186 std::scoped_lock lockGuard(mLock);
1187 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
1188 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
1189 "client died");
1190 }
1191 auto result = mSubscriptionManager->subscribeSupportedValueChange(callback,
1192 propIdAreaIdsToSubscribe);
1193 if (!result.ok()) {
1194 ALOGW("registerSupportedValueChangeCallback: failed to subscribe supported value change"
1195 " for %s, error: %s",
1196 fmt::format("{}", propIdAreaIdsToSubscribe).c_str(),
1197 result.error().message().c_str());
1198 return toScopedAStatus(result);
1199 }
1200 }
1201 return ScopedAStatus::ok();
1202 }
1203
unregisterSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback> & callback,const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds)1204 ScopedAStatus DefaultVehicleHal::unregisterSupportedValueChangeCallback(
1205 const std::shared_ptr<IVehicleCallback>& callback,
1206 const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
1207 std::vector<PropIdAreaId> propIdAreaIds;
1208 for (const auto& vhalPropIdAreaId : vhalPropIdAreaIds) {
1209 propIdAreaIds.push_back(
1210 PropIdAreaId{.propId = vhalPropIdAreaId.propId, .areaId = vhalPropIdAreaId.areaId});
1211 }
1212
1213 auto result = mSubscriptionManager->unsubscribeSupportedValueChange(callback->asBinder().get(),
1214 propIdAreaIds);
1215 if (!result.ok()) {
1216 ALOGW("unregisterSupportedValueChangeCallback: failed to unsubscribe supported value change"
1217 " for %s, error: %s",
1218 fmt::format("{}", propIdAreaIds).c_str(), result.error().message().c_str());
1219 return toScopedAStatus(result);
1220 }
1221 return ScopedAStatus::ok();
1222 }
1223
getHardware()1224 IVehicleHardware* DefaultVehicleHal::getHardware() {
1225 return mVehicleHardware.get();
1226 }
1227
checkPermissionHelper(const VehiclePropValue & value,VehiclePropertyAccess accessToTest) const1228 VhalResult<void> DefaultVehicleHal::checkPermissionHelper(
1229 const VehiclePropValue& value, VehiclePropertyAccess accessToTest) const {
1230 static const std::unordered_set<VehiclePropertyAccess> validAccesses = {
1231 VehiclePropertyAccess::WRITE, VehiclePropertyAccess::READ,
1232 VehiclePropertyAccess::READ_WRITE};
1233 if (validAccesses.find(accessToTest) == validAccesses.end()) {
1234 return StatusError(StatusCode::INVALID_ARG)
1235 << "checkPermissionHelper parameter is an invalid access type";
1236 }
1237
1238 int32_t propId = value.prop;
1239 auto result = getConfig(propId);
1240 if (!result.ok()) {
1241 return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
1242 }
1243
1244 const VehiclePropConfig& config = result.value();
1245 const VehicleAreaConfig* areaConfig = getAreaConfig(value, config);
1246
1247 if (areaConfig == nullptr && !isGlobalProp(propId)) {
1248 return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId;
1249 }
1250 if (!hasRequiredAccess(config.access, accessToTest) &&
1251 (areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
1252 return StatusError(StatusCode::ACCESS_DENIED)
1253 << StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
1254 propId, static_cast<int32_t>(accessToTest));
1255 }
1256 return {};
1257 }
1258
checkWritePermission(const VehiclePropValue & value) const1259 VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
1260 return checkPermissionHelper(value, VehiclePropertyAccess::WRITE);
1261 }
1262
checkReadPermission(const VehiclePropValue & value) const1263 VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
1264 return checkPermissionHelper(value, VehiclePropertyAccess::READ);
1265 }
1266
checkHealth(IVehicleHardware * vehicleHardware,std::weak_ptr<SubscriptionManager> subscriptionManager)1267 void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
1268 std::weak_ptr<SubscriptionManager> subscriptionManager) {
1269 StatusCode status = vehicleHardware->checkHealth();
1270 if (status != StatusCode::OK) {
1271 ALOGE("VHAL check health returns non-okay status");
1272 return;
1273 }
1274 std::vector<VehiclePropValue> values = {{
1275 .areaId = 0,
1276 .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
1277 .status = VehiclePropertyStatus::AVAILABLE,
1278 .value.int64Values = {uptimeMillis()},
1279 }};
1280 onPropertyChangeEvent(subscriptionManager, std::move(values));
1281 return;
1282 }
1283
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)1284 binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath(
1285 AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
1286 return AIBinder_linkToDeath(binder, recipient, cookie);
1287 }
1288
isAlive(const AIBinder * binder)1289 bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) {
1290 return AIBinder_isAlive(binder);
1291 }
1292
setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> handler)1293 void DefaultVehicleHal::setBinderLifecycleHandler(
1294 std::unique_ptr<BinderLifecycleInterface> handler) {
1295 mBinderLifecycleHandler = std::move(handler);
1296 }
1297
checkDumpPermission()1298 bool DefaultVehicleHal::checkDumpPermission() {
1299 uid_t uid = AIBinder_getCallingUid();
1300 return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
1301 }
1302
dump(int fd,const char ** args,uint32_t numArgs)1303 binder_status_t DefaultVehicleHal::dump(int fd, const char** args, uint32_t numArgs) {
1304 if (!checkDumpPermission()) {
1305 dprintf(fd, "Caller must be root, system or shell");
1306 return STATUS_PERMISSION_DENIED;
1307 }
1308
1309 std::vector<std::string> options;
1310 for (uint32_t i = 0; i < numArgs; i++) {
1311 options.push_back(args[i]);
1312 }
1313 if (options.size() == 1 && options[0] == "-a") {
1314 // Ignore "-a" option. Bugreport will call with this option.
1315 options.clear();
1316 }
1317 DumpResult result = mVehicleHardware->dump(options);
1318 if (result.refreshPropertyConfigs) {
1319 getAllPropConfigsFromHardwareLocked();
1320 }
1321 dprintf(fd, "%s", (result.buffer + "\n").c_str());
1322 if (!result.callerShouldDumpState) {
1323 return STATUS_OK;
1324 }
1325 dprintf(fd, "Vehicle HAL State: \n");
1326 std::unordered_map<int32_t, VehiclePropConfig> configsByPropIdCopy;
1327 getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
1328 SharedScopedLockAssertion lockAssertion(mConfigLock);
1329
1330 configsByPropIdCopy = configsByPropId;
1331 });
1332 {
1333 std::scoped_lock<std::mutex> lockGuard(mLock);
1334 dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
1335 dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
1336 dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
1337 dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
1338 dprintf(fd, "Currently have %zu subscribe clients\n",
1339 mSubscriptionManager->countPropertyChangeClients());
1340 dprintf(fd, "Currently have %zu supported values change subscribe clients\n",
1341 mSubscriptionManager->countSupportedValueChangeClients());
1342 }
1343 return STATUS_OK;
1344 }
1345
countClients()1346 size_t DefaultVehicleHal::countClients() {
1347 std::scoped_lock<std::mutex> lockGuard(mLock);
1348 return mGetValuesClients.size() + mSetValuesClients.size() +
1349 mSubscriptionManager->countPropertyChangeClients() +
1350 mSubscriptionManager->countSupportedValueChangeClients();
1351 }
1352
1353 } // namespace vehicle
1354 } // namespace automotive
1355 } // namespace hardware
1356 } // namespace android
1357