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::SetValueRequest;
53 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
54 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
55 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
56 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
57 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
58 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
59 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
60 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
61 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
62 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
63 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
64 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
65 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
66 using ::aidl::android::hardware::automotive::vehicle::VersionForVehicleProperty;
67 using ::android::automotive::car_binder_lib::LargeParcelableBase;
68 using ::android::base::Error;
69 using ::android::base::expected;
70 using ::android::base::Result;
71 using ::android::base::StringPrintf;
72
73 using ::ndk::ScopedAIBinder_DeathRecipient;
74 using ::ndk::ScopedAStatus;
75 using ::ndk::ScopedFileDescriptor;
76
toString(const std::unordered_set<int64_t> & values)77 std::string toString(const std::unordered_set<int64_t>& values) {
78 std::string str = "";
79 for (auto it = values.begin(); it != values.end(); it++) {
80 str += std::to_string(*it);
81 if (std::next(it, 1) != values.end()) {
82 str += ", ";
83 }
84 }
85 return str;
86 }
87
getDefaultSampleRateHz(float sampleRateHz,float minSampleRateHz,float maxSampleRateHz)88 float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) {
89 if (sampleRateHz < minSampleRateHz) {
90 return minSampleRateHz;
91 }
92 if (sampleRateHz > maxSampleRateHz) {
93 return maxSampleRateHz;
94 }
95 return sampleRateHz;
96 }
97
98 class SCOPED_CAPABILITY SharedScopedLockAssertion {
99 public:
ACQUIRE_SHARED(mutex)100 SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {}
RELEASE()101 ~SharedScopedLockAssertion() RELEASE() {}
102 };
103
104 class SCOPED_CAPABILITY UniqueScopedLockAssertion {
105 public:
ACQUIRE(mutex)106 UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {}
RELEASE()107 ~UniqueScopedLockAssertion() RELEASE() {}
108 };
109
110 } // namespace
111
DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)112 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
113 : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0) {};
114
DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,int32_t testInterfaceVersion)115 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
116 int32_t testInterfaceVersion)
117 : mVehicleHardware(std::move(vehicleHardware)),
118 mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
119 mTestInterfaceVersion(testInterfaceVersion) {
120 ALOGD("DefaultVehicleHal init");
121 IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
122 mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
123 mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
124 if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
125 mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
126 mPropertyChangeEventsBatchingConsumer =
127 std::make_shared<BatchingConsumer<VehiclePropValue>>();
128 mPropertyChangeEventsBatchingConsumer->run(
129 mBatchedEventQueue.get(), mEventBatchingWindow,
130 [this](std::vector<VehiclePropValue> batchedEvents) {
131 handleBatchedPropertyEvents(std::move(batchedEvents));
132 });
133 }
134
135 std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
136 std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
137 std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
138 mVehicleHardware->registerOnPropertyChangeEvent(
139 std::make_unique<IVehicleHardware::PropertyChangeCallback>(
140 [subscriptionManagerCopy, batchedEventQueueCopy,
141 eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
142 if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
143 batchPropertyChangeEvent(batchedEventQueueCopy,
144 std::move(updatedValues));
145 } else {
146 onPropertyChangeEvent(subscriptionManagerCopy,
147 std::move(updatedValues));
148 }
149 }));
150 mVehicleHardware->registerOnPropertySetErrorEvent(
151 std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
152 [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
153 onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
154 }));
155
156 // Register heartbeat event.
157 mRecurrentAction = std::make_shared<std::function<void()>>(
158 [vehicleHardwarePtr, subscriptionManagerCopy]() {
159 checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
160 });
161 mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
162
163 mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
164 mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
165 mDeathRecipient = ScopedAIBinder_DeathRecipient(
166 AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
167 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
168 &DefaultVehicleHal::onBinderUnlinked);
169 }
170
~DefaultVehicleHal()171 DefaultVehicleHal::~DefaultVehicleHal() {
172 // Delete the deathRecipient so that onBinderDied would not be called to reference 'this'.
173 mDeathRecipient = ScopedAIBinder_DeathRecipient();
174 mBinderEvents.deactivate();
175 if (mOnBinderDiedUnlinkedHandlerThread.joinable()) {
176 mOnBinderDiedUnlinkedHandlerThread.join();
177 }
178 // mRecurrentAction uses pointer to mVehicleHardware, so it has to be unregistered before
179 // mVehicleHardware.
180 mRecurrentTimer.unregisterTimerCallback(mRecurrentAction);
181
182 if (mBatchedEventQueue) {
183 // mPropertyChangeEventsBatchingConsumer uses mSubscriptionManager and mBatchedEventQueue.
184 mBatchedEventQueue->deactivate();
185 mPropertyChangeEventsBatchingConsumer->requestStop();
186 mPropertyChangeEventsBatchingConsumer->waitStopped();
187 mPropertyChangeEventsBatchingConsumer.reset();
188 mBatchedEventQueue.reset();
189 }
190
191 // mSubscriptionManager uses pointer to mVehicleHardware, so it has to be destroyed before
192 // mVehicleHardware.
193 mSubscriptionManager.reset();
194 mVehicleHardware.reset();
195 }
196
batchPropertyChangeEvent(const std::weak_ptr<ConcurrentQueue<VehiclePropValue>> & batchedEventQueue,std::vector<VehiclePropValue> && updatedValues)197 void DefaultVehicleHal::batchPropertyChangeEvent(
198 const std::weak_ptr<ConcurrentQueue<VehiclePropValue>>& batchedEventQueue,
199 std::vector<VehiclePropValue>&& updatedValues) {
200 auto batchedEventQueueStrong = batchedEventQueue.lock();
201 if (batchedEventQueueStrong == nullptr) {
202 ALOGW("the batched property events queue is destroyed, DefaultVehicleHal is ending");
203 return;
204 }
205 batchedEventQueueStrong->push(std::move(updatedValues));
206 }
207
handleBatchedPropertyEvents(std::vector<VehiclePropValue> && batchedEvents)208 void DefaultVehicleHal::handleBatchedPropertyEvents(std::vector<VehiclePropValue>&& batchedEvents) {
209 onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents));
210 }
211
onPropertyChangeEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,std::vector<VehiclePropValue> && updatedValues)212 void DefaultVehicleHal::onPropertyChangeEvent(
213 const std::weak_ptr<SubscriptionManager>& subscriptionManager,
214 std::vector<VehiclePropValue>&& updatedValues) {
215 ATRACE_CALL();
216 auto manager = subscriptionManager.lock();
217 if (manager == nullptr) {
218 ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
219 return;
220 }
221 auto updatedValuesByClients = manager->getSubscribedClients(std::move(updatedValues));
222 for (auto& [callback, values] : updatedValuesByClients) {
223 SubscriptionClient::sendUpdatedValues(callback, std::move(values));
224 }
225 }
226
onPropertySetErrorEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,const std::vector<SetValueErrorEvent> & errorEvents)227 void DefaultVehicleHal::onPropertySetErrorEvent(
228 const std::weak_ptr<SubscriptionManager>& subscriptionManager,
229 const std::vector<SetValueErrorEvent>& errorEvents) {
230 auto manager = subscriptionManager.lock();
231 if (manager == nullptr) {
232 ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
233 return;
234 }
235 auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents);
236 for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) {
237 SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors));
238 }
239 }
240
241 template <class T>
getOrCreateClient(std::unordered_map<const AIBinder *,std::shared_ptr<T>> * clients,const CallbackType & callback,std::shared_ptr<PendingRequestPool> pendingRequestPool)242 std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
243 std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
244 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
245 const AIBinder* clientId = callback->asBinder().get();
246 if (clients->find(clientId) == clients->end()) {
247 (*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
248 }
249 return (*clients)[clientId];
250 }
251
monitorBinderLifeCycleLocked(const AIBinder * clientId)252 bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) {
253 OnBinderDiedContext* contextPtr = nullptr;
254 if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
255 return mBinderLifecycleHandler->isAlive(clientId);
256 } else {
257 std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
258 OnBinderDiedContext{.vhal = this, .clientId = clientId});
259 // We know context must be alive when we use contextPtr because context would only
260 // be removed in OnBinderUnlinked, which must be called after OnBinderDied.
261 contextPtr = context.get();
262 // Insert into a map to keep the context object alive.
263 mOnBinderDiedContexts[clientId] = std::move(context);
264 }
265
266 // If this function fails, onBinderUnlinked would be called to remove the added context.
267 binder_status_t status = mBinderLifecycleHandler->linkToDeath(
268 const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
269 if (status == STATUS_OK) {
270 return true;
271 }
272 ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
273 static_cast<int>(status));
274 return false;
275 }
276
onBinderDied(void * cookie)277 void DefaultVehicleHal::onBinderDied(void* cookie) {
278 OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
279 // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
280 // thread because we might be holding the mLock the handler requires.
281 context->vhal->mBinderEvents.push(
282 BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId});
283 }
284
onBinderDiedWithContext(const AIBinder * clientId)285 void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) {
286 std::scoped_lock<std::mutex> lockGuard(mLock);
287 ALOGD("binder died, client ID: %p", clientId);
288 mSetValuesClients.erase(clientId);
289 mGetValuesClients.erase(clientId);
290 mSubscriptionManager->unsubscribe(clientId);
291 }
292
onBinderUnlinked(void * cookie)293 void DefaultVehicleHal::onBinderUnlinked(void* cookie) {
294 OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
295 // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
296 // thread because we might be holding the mLock the handler requires.
297 context->vhal->mBinderEvents.push(
298 BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId});
299 }
300
onBinderUnlinkedWithContext(const AIBinder * clientId)301 void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) {
302 ALOGD("binder unlinked");
303 std::scoped_lock<std::mutex> lockGuard(mLock);
304 // Delete the context associated with this cookie.
305 mOnBinderDiedContexts.erase(clientId);
306 }
307
onBinderDiedUnlinkedHandler()308 void DefaultVehicleHal::onBinderDiedUnlinkedHandler() {
309 while (mBinderEvents.waitForItems()) {
310 for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) {
311 if (event.forOnBinderDied) {
312 onBinderDiedWithContext(event.clientId);
313 } else {
314 onBinderUnlinkedWithContext(event.clientId);
315 }
316 }
317 }
318 }
319
320 template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
321 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
322 std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
323 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
324 template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
325 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
326 std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
327 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
328
setTimeout(int64_t timeoutInNano)329 void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
330 mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
331 }
332
getVhalInterfaceVersion() const333 int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
334 if (mTestInterfaceVersion != 0) {
335 return mTestInterfaceVersion;
336 }
337 int32_t myVersion = 0;
338 // getInterfaceVersion is in-reality a const method.
339 const_cast<DefaultVehicleHal*>(this)->getInterfaceVersion(&myVersion);
340 return myVersion;
341 }
342
isConfigSupportedForCurrentVhalVersion(const VehiclePropConfig & config) const343 bool DefaultVehicleHal::isConfigSupportedForCurrentVhalVersion(
344 const VehiclePropConfig& config) const {
345 int32_t myVersion = getVhalInterfaceVersion();
346 if (!isSystemProp(config.prop)) {
347 return true;
348 }
349 VehicleProperty property = static_cast<VehicleProperty>(config.prop);
350 std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
351 auto it = VersionForVehicleProperty.find(property);
352 if (it == VersionForVehicleProperty.end()) {
353 ALOGE("The property: %s is not a supported system property, ignore", propertyName.c_str());
354 return false;
355 }
356 int requiredVersion = it->second;
357 if (myVersion < requiredVersion) {
358 ALOGE("The property: %s is not supported for current client VHAL version, "
359 "require %d, current version: %d, ignore",
360 propertyName.c_str(), requiredVersion, myVersion);
361 return false;
362 }
363 return true;
364 }
365
getAllPropConfigsFromHardwareLocked() const366 bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
367 ALOGD("Get all property configs from hardware");
368 auto configs = mVehicleHardware->getAllPropertyConfigs();
369 std::vector<VehiclePropConfig> filteredConfigs;
370 for (const auto& config : configs) {
371 if (isConfigSupportedForCurrentVhalVersion(config)) {
372 filteredConfigs.push_back(std::move(config));
373 }
374 }
375
376 {
377 std::unique_lock<std::shared_timed_mutex> configWriteLock(mConfigLock);
378 UniqueScopedLockAssertion lockAssertion(mConfigLock);
379
380 for (auto& config : filteredConfigs) {
381 mConfigsByPropId[config.prop] = config;
382 }
383 VehiclePropConfigs vehiclePropConfigs;
384 vehiclePropConfigs.payloads = std::move(filteredConfigs);
385 auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
386 if (!result.ok()) {
387 ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
388 result.error().message().c_str(), static_cast<int>(result.error().code()));
389 mConfigFile = nullptr;
390 return false;
391 }
392
393 if (result.value() != nullptr) {
394 mConfigFile = std::move(result.value());
395 }
396 }
397
398 mConfigInit = true;
399 return true;
400 }
401
getConfigsByPropId(std::function<void (const std::unordered_map<int32_t,VehiclePropConfig> &)> callback) const402 void DefaultVehicleHal::getConfigsByPropId(
403 std::function<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
404 if (!mConfigInit) {
405 CHECK(getAllPropConfigsFromHardwareLocked())
406 << "Failed to get property configs from hardware";
407 }
408
409 std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
410 SharedScopedLockAssertion lockAssertion(mConfigLock);
411
412 callback(mConfigsByPropId);
413 }
414
getAllPropConfigs(VehiclePropConfigs * output)415 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
416 if (!mConfigInit) {
417 CHECK(getAllPropConfigsFromHardwareLocked())
418 << "Failed to get property configs from hardware";
419 }
420
421 std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
422 SharedScopedLockAssertion lockAssertion(mConfigLock);
423
424 if (mConfigFile != nullptr) {
425 output->payloads.clear();
426 output->sharedMemoryFd.set(dup(mConfigFile->get()));
427 return ScopedAStatus::ok();
428 }
429
430 output->payloads.reserve(mConfigsByPropId.size());
431 for (const auto& [_, config] : mConfigsByPropId) {
432 output->payloads.push_back(config);
433 }
434 return ScopedAStatus::ok();
435 }
436
getConfig(int32_t propId) const437 Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
438 Result<VehiclePropConfig> result;
439
440 if (!mConfigInit) {
441 std::optional<VehiclePropConfig> config = mVehicleHardware->getPropertyConfig(propId);
442 if (!config.has_value()) {
443 return Error() << "no config for property, ID: " << propId;
444 }
445 if (!isConfigSupportedForCurrentVhalVersion(config.value())) {
446 return Error() << "property not supported for current VHAL interface, ID: " << propId;
447 }
448
449 return config.value();
450 }
451
452 getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
453 SharedScopedLockAssertion lockAssertion(mConfigLock);
454
455 auto it = configsByPropId.find(propId);
456 if (it == configsByPropId.end()) {
457 result = Error() << "no config for property, ID: " << propId;
458 return;
459 }
460 // Copy the VehiclePropConfig
461 result = it->second;
462 });
463 return result;
464 }
465
checkProperty(const VehiclePropValue & propValue)466 Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
467 int32_t propId = propValue.prop;
468 auto result = getConfig(propId);
469 if (!result.ok()) {
470 return result.error();
471 }
472 const VehiclePropConfig& config = result.value();
473 const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
474 if (!isGlobalProp(propId) && areaConfig == nullptr) {
475 // Ignore areaId for global property. For non global property, check whether areaId is
476 // allowed. areaId must appear in areaConfig.
477 return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
478 << ", not listed in config";
479 }
480 if (auto result = checkPropValue(propValue, &config); !result.ok()) {
481 return Error() << "invalid property value: " << propValue.toString()
482 << ", error: " << getErrorMsg(result);
483 }
484 if (auto result = checkValueRange(propValue, areaConfig); !result.ok()) {
485 return Error() << "property value out of range: " << propValue.toString()
486 << ", error: " << getErrorMsg(result);
487 }
488 return {};
489 }
490
getValues(const CallbackType & callback,const GetValueRequests & requests)491 ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
492 const GetValueRequests& requests) {
493 ATRACE_CALL();
494 if (callback == nullptr) {
495 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
496 }
497 expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
498 deserializedResults = fromStableLargeParcelable(requests);
499 if (!deserializedResults.ok()) {
500 ALOGE("getValues: failed to parse getValues requests");
501 return std::move(deserializedResults.error());
502 }
503 const std::vector<GetValueRequest>& getValueRequests =
504 deserializedResults.value().getObject()->payloads;
505
506 auto maybeRequestIds = checkDuplicateRequests(getValueRequests);
507 if (!maybeRequestIds.ok()) {
508 ALOGE("getValues: duplicate request ID");
509 return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
510 }
511
512 // A list of failed result we already know before sending to hardware.
513 std::vector<GetValueResult> failedResults;
514 // The list of requests that we would send to hardware.
515 std::vector<GetValueRequest> hardwareRequests;
516
517 for (const auto& request : getValueRequests) {
518 if (auto result = checkReadPermission(request.prop); !result.ok()) {
519 ALOGW("property does not support reading: %s", getErrorMsg(result).c_str());
520 failedResults.push_back(GetValueResult{
521 .requestId = request.requestId,
522 .status = getErrorCode(result),
523 .prop = {},
524 });
525 continue;
526 }
527 hardwareRequests.push_back(request);
528 }
529
530 // The set of request Ids that we would send to hardware.
531 std::unordered_set<int64_t> hardwareRequestIds;
532 for (const auto& request : hardwareRequests) {
533 hardwareRequestIds.insert(request.requestId);
534 }
535
536 std::shared_ptr<GetValuesClient> client;
537 {
538 // Lock to make sure onBinderDied would not be called concurrently.
539 std::scoped_lock lockGuard(mLock);
540 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
541 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
542 "client died");
543 }
544
545 client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
546 }
547
548 // Register the pending hardware requests and also check for duplicate request Ids.
549 if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
550 ALOGE("getValues[%s]: failed to add pending requests, error: %s",
551 toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
552 return toScopedAStatus(addRequestResult);
553 }
554
555 if (!failedResults.empty()) {
556 // First send the failed results we already know back to the client.
557 client->sendResults(std::move(failedResults));
558 }
559
560 if (hardwareRequests.empty()) {
561 return ScopedAStatus::ok();
562 }
563
564 if (StatusCode status =
565 mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests);
566 status != StatusCode::OK) {
567 // If the hardware returns error, finish all the pending requests for this request because
568 // we never expect hardware to call callback for these requests.
569 client->tryFinishRequests(hardwareRequestIds);
570 ALOGE("getValues[%s]: failed to get value from VehicleHardware, status: %d",
571 toString(hardwareRequestIds).c_str(), toInt(status));
572 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
573 toInt(status), "failed to get value from VehicleHardware");
574 }
575 return ScopedAStatus::ok();
576 }
577
setValues(const CallbackType & callback,const SetValueRequests & requests)578 ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
579 const SetValueRequests& requests) {
580 ATRACE_CALL();
581 if (callback == nullptr) {
582 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
583 }
584 expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
585 deserializedResults = fromStableLargeParcelable(requests);
586 if (!deserializedResults.ok()) {
587 ALOGE("setValues: failed to parse setValues requests");
588 return std::move(deserializedResults.error());
589 }
590 const std::vector<SetValueRequest>& setValueRequests =
591 deserializedResults.value().getObject()->payloads;
592
593 // A list of failed result we already know before sending to hardware.
594 std::vector<SetValueResult> failedResults;
595 // The list of requests that we would send to hardware.
596 std::vector<SetValueRequest> hardwareRequests;
597
598 auto maybeRequestIds = checkDuplicateRequests(setValueRequests);
599 if (!maybeRequestIds.ok()) {
600 ALOGE("setValues: duplicate request ID");
601 return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
602 }
603
604 for (auto& request : setValueRequests) {
605 int64_t requestId = request.requestId;
606 if (auto result = checkWritePermission(request.value); !result.ok()) {
607 ALOGW("property does not support writing: %s", getErrorMsg(result).c_str());
608 failedResults.push_back(SetValueResult{
609 .requestId = requestId,
610 .status = getErrorCode(result),
611 });
612 continue;
613 }
614 if (auto result = checkProperty(request.value); !result.ok()) {
615 ALOGW("setValues[%" PRId64 "]: property is not valid: %s", requestId,
616 getErrorMsg(result).c_str());
617 failedResults.push_back(SetValueResult{
618 .requestId = requestId,
619 .status = StatusCode::INVALID_ARG,
620 });
621 continue;
622 }
623
624 hardwareRequests.push_back(request);
625 }
626
627 // The set of request Ids that we would send to hardware.
628 std::unordered_set<int64_t> hardwareRequestIds;
629 for (const auto& request : hardwareRequests) {
630 hardwareRequestIds.insert(request.requestId);
631 }
632
633 std::shared_ptr<SetValuesClient> client;
634 {
635 // Lock to make sure onBinderDied would not be called concurrently.
636 std::scoped_lock lockGuard(mLock);
637 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
638 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
639 "client died");
640 }
641 client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
642 }
643
644 // Register the pending hardware requests and also check for duplicate request Ids.
645 if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
646 ALOGE("setValues[%s], failed to add pending requests, error: %s",
647 toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
648 return toScopedAStatus(addRequestResult);
649 }
650
651 if (!failedResults.empty()) {
652 // First send the failed results we already know back to the client.
653 client->sendResults(std::move(failedResults));
654 }
655
656 if (hardwareRequests.empty()) {
657 return ScopedAStatus::ok();
658 }
659
660 if (StatusCode status =
661 mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
662 status != StatusCode::OK) {
663 // If the hardware returns error, finish all the pending requests for this request because
664 // we never expect hardware to call callback for these requests.
665 client->tryFinishRequests(hardwareRequestIds);
666 ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d",
667 toString(hardwareRequestIds).c_str(), toInt(status));
668 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
669 toInt(status), "failed to set value to VehicleHardware");
670 }
671
672 return ScopedAStatus::ok();
673 }
674
675 #define CHECK_DUPLICATE_REQUESTS(PROP_NAME) \
676 do { \
677 std::vector<int64_t> requestIds; \
678 std::set<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> requestProps; \
679 for (const auto& request : requests) { \
680 const auto& prop = request.PROP_NAME; \
681 if (requestProps.count(prop) != 0) { \
682 return ::android::base::Error() \
683 << "duplicate request for property: " << prop.toString(); \
684 } \
685 requestProps.insert(prop); \
686 requestIds.push_back(request.requestId); \
687 } \
688 return requestIds; \
689 } while (0);
690
checkDuplicateRequests(const std::vector<GetValueRequest> & requests)691 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
692 const std::vector<GetValueRequest>& requests) {
693 CHECK_DUPLICATE_REQUESTS(prop);
694 }
695
checkDuplicateRequests(const std::vector<SetValueRequest> & requests)696 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
697 const std::vector<SetValueRequest>& requests) {
698 CHECK_DUPLICATE_REQUESTS(value);
699 }
700
701 #undef CHECK_DUPLICATE_REQUESTS
702
getPropConfigs(const std::vector<int32_t> & props,VehiclePropConfigs * output)703 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
704 VehiclePropConfigs* output) {
705 std::vector<VehiclePropConfig> configs;
706
707 if (!mConfigInit) {
708 for (int32_t prop : props) {
709 auto maybeConfig = mVehicleHardware->getPropertyConfig(prop);
710 if (!maybeConfig.has_value() ||
711 !isConfigSupportedForCurrentVhalVersion(maybeConfig.value())) {
712 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
713 toInt(StatusCode::INVALID_ARG),
714 StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
715 }
716 configs.push_back(maybeConfig.value());
717 }
718
719 return vectorToStableLargeParcelable(std::move(configs), output);
720 }
721
722 ScopedAStatus status = ScopedAStatus::ok();
723 getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
724 SharedScopedLockAssertion lockAssertion(mConfigLock);
725
726 for (int32_t prop : props) {
727 auto it = configsByPropId.find(prop);
728 if (it != configsByPropId.end()) {
729 configs.push_back(it->second);
730 } else {
731 status = ScopedAStatus::fromServiceSpecificErrorWithMessage(
732 toInt(StatusCode::INVALID_ARG),
733 StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
734 return;
735 }
736 }
737 });
738
739 if (!status.isOk()) {
740 return status;
741 }
742
743 return vectorToStableLargeParcelable(std::move(configs), output);
744 }
745
hasRequiredAccess(VehiclePropertyAccess access,VehiclePropertyAccess requiredAccess)746 bool hasRequiredAccess(VehiclePropertyAccess access, VehiclePropertyAccess requiredAccess) {
747 return access == requiredAccess || access == VehiclePropertyAccess::READ_WRITE;
748 }
749
areaConfigsHaveRequiredAccess(const std::vector<VehicleAreaConfig> & areaConfigs,VehiclePropertyAccess requiredAccess)750 bool areaConfigsHaveRequiredAccess(const std::vector<VehicleAreaConfig>& areaConfigs,
751 VehiclePropertyAccess requiredAccess) {
752 if (areaConfigs.empty()) {
753 return false;
754 }
755 for (VehicleAreaConfig areaConfig : areaConfigs) {
756 if (!hasRequiredAccess(areaConfig.access, requiredAccess)) {
757 return false;
758 }
759 }
760 return true;
761 }
762
checkSubscribeOptions(const std::vector<SubscribeOptions> & options,const std::unordered_map<int32_t,VehiclePropConfig> & configsByPropId)763 VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
764 const std::vector<SubscribeOptions>& options,
765 const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId) {
766 for (const auto& option : options) {
767 int32_t propId = option.propId;
768 auto it = configsByPropId.find(propId);
769 if (it == configsByPropId.end()) {
770 return StatusError(StatusCode::INVALID_ARG)
771 << StringPrintf("no config for property, ID: %" PRId32, propId);
772 }
773 const VehiclePropConfig& config = it->second;
774 std::vector<VehicleAreaConfig> areaConfigs;
775 if (option.areaIds.empty()) {
776 areaConfigs = config.areaConfigs;
777 } else {
778 std::unordered_map<int, VehicleAreaConfig> areaConfigByAreaId;
779 for (const VehicleAreaConfig& areaConfig : config.areaConfigs) {
780 areaConfigByAreaId.emplace(areaConfig.areaId, areaConfig);
781 }
782 for (int areaId : option.areaIds) {
783 auto it = areaConfigByAreaId.find(areaId);
784 if (it != areaConfigByAreaId.end()) {
785 areaConfigs.push_back(it->second);
786 } else if (areaId != 0 || !areaConfigByAreaId.empty()) {
787 return StatusError(StatusCode::INVALID_ARG)
788 << StringPrintf("invalid area ID: %" PRId32 " for prop ID: %" PRId32
789 ", not listed in config",
790 areaId, propId);
791 }
792 }
793 }
794
795 if (config.changeMode != VehiclePropertyChangeMode::ON_CHANGE &&
796 config.changeMode != VehiclePropertyChangeMode::CONTINUOUS) {
797 return StatusError(StatusCode::INVALID_ARG)
798 << "only support subscribing to ON_CHANGE or CONTINUOUS property";
799 }
800
801 // Either VehiclePropConfig.access or VehicleAreaConfig.access will be specified
802 if (!hasRequiredAccess(config.access, VehiclePropertyAccess::READ) &&
803 !areaConfigsHaveRequiredAccess(areaConfigs, VehiclePropertyAccess::READ)) {
804 return StatusError(StatusCode::ACCESS_DENIED)
805 << StringPrintf("Property %" PRId32 " has no read access", propId);
806 }
807
808 if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
809 float sampleRateHz = option.sampleRate;
810 float minSampleRateHz = config.minSampleRate;
811 float maxSampleRateHz = config.maxSampleRate;
812 float defaultRateHz =
813 getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz);
814 if (sampleRateHz != defaultRateHz) {
815 ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f "
816 "HZ",
817 sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz);
818 sampleRateHz = defaultRateHz;
819 }
820 if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) {
821 return StatusError(StatusCode::INVALID_ARG)
822 << "invalid sample rate: " << sampleRateHz << " HZ";
823 }
824 if (!SubscriptionManager::checkResolution(option.resolution)) {
825 return StatusError(StatusCode::INVALID_ARG)
826 << "invalid resolution: " << option.resolution;
827 }
828 }
829 }
830
831 return {};
832 }
833
parseSubscribeOptions(const std::vector<SubscribeOptions> & options,const std::unordered_map<int32_t,VehiclePropConfig> & configsByPropId,std::vector<SubscribeOptions> & onChangeSubscriptions,std::vector<SubscribeOptions> & continuousSubscriptions)834 void DefaultVehicleHal::parseSubscribeOptions(
835 const std::vector<SubscribeOptions>& options,
836 const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
837 std::vector<SubscribeOptions>& onChangeSubscriptions,
838 std::vector<SubscribeOptions>& continuousSubscriptions) {
839 for (const auto& option : options) {
840 int32_t propId = option.propId;
841 // We have already validate config exists.
842 const VehiclePropConfig& config = configsByPropId.at(propId);
843
844 SubscribeOptions optionCopy = option;
845 // If areaIds is empty, subscribe to all areas.
846 if (optionCopy.areaIds.empty() && !isGlobalProp(propId)) {
847 for (const auto& areaConfig : config.areaConfigs) {
848 optionCopy.areaIds.push_back(areaConfig.areaId);
849 }
850 }
851
852 if (isGlobalProp(propId)) {
853 optionCopy.areaIds = {0};
854 }
855
856 if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
857 optionCopy.sampleRate = getDefaultSampleRateHz(
858 optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate);
859 if (!optionCopy.enableVariableUpdateRate) {
860 continuousSubscriptions.push_back(std::move(optionCopy));
861 } else {
862 // If clients enables to VUR, we need to check whether VUR is supported for the
863 // specific [propId, areaId] and overwrite the option to disable if not supported.
864 std::vector<int32_t> areasVurEnabled;
865 std::vector<int32_t> areasVurDisabled;
866 for (int32_t areaId : optionCopy.areaIds) {
867 const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
868 if (areaConfig == nullptr) {
869 areasVurDisabled.push_back(areaId);
870 continue;
871 }
872 if (!areaConfig->supportVariableUpdateRate) {
873 areasVurDisabled.push_back(areaId);
874 continue;
875 }
876 areasVurEnabled.push_back(areaId);
877 }
878 if (!areasVurEnabled.empty()) {
879 SubscribeOptions optionVurEnabled = optionCopy;
880 optionVurEnabled.areaIds = areasVurEnabled;
881 optionVurEnabled.enableVariableUpdateRate = true;
882 continuousSubscriptions.push_back(std::move(optionVurEnabled));
883 }
884
885 if (!areasVurDisabled.empty()) {
886 // We use optionCopy for areas with VUR disabled.
887 optionCopy.areaIds = areasVurDisabled;
888 optionCopy.enableVariableUpdateRate = false;
889 continuousSubscriptions.push_back(std::move(optionCopy));
890 }
891 }
892 } else {
893 onChangeSubscriptions.push_back(std::move(optionCopy));
894 }
895 }
896 }
897
subscribe(const CallbackType & callback,const std::vector<SubscribeOptions> & options,int32_t maxSharedMemoryFileCount)898 ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
899 const std::vector<SubscribeOptions>& options,
900 [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
901 // TODO(b/205189110): Use shared memory file count.
902 if (callback == nullptr) {
903 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
904 }
905 std::vector<SubscribeOptions> onChangeSubscriptions;
906 std::vector<SubscribeOptions> continuousSubscriptions;
907 ScopedAStatus returnStatus = ScopedAStatus::ok();
908 getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions,
909 &continuousSubscriptions](const auto& configsByPropId) {
910 SharedScopedLockAssertion lockAssertion(mConfigLock);
911
912 if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) {
913 ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
914 returnStatus = toScopedAStatus(result);
915 return;
916 }
917 parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions,
918 continuousSubscriptions);
919 });
920
921 if (!returnStatus.isOk()) {
922 return returnStatus;
923 }
924
925 {
926 // Lock to make sure onBinderDied would not be called concurrently.
927 std::scoped_lock lockGuard(mLock);
928 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
929 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
930 "client died");
931 }
932
933 if (!onChangeSubscriptions.empty()) {
934 auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
935 /*isContinuousProperty=*/false);
936 if (!result.ok()) {
937 return toScopedAStatus(result);
938 }
939 }
940 if (!continuousSubscriptions.empty()) {
941 auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions,
942 /*isContinuousProperty=*/true);
943 if (!result.ok()) {
944 return toScopedAStatus(result);
945 }
946 }
947 }
948 return ScopedAStatus::ok();
949 }
950
unsubscribe(const CallbackType & callback,const std::vector<int32_t> & propIds)951 ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType& callback,
952 const std::vector<int32_t>& propIds) {
953 if (callback == nullptr) {
954 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
955 }
956 return toScopedAStatus(mSubscriptionManager->unsubscribe(callback->asBinder().get(), propIds));
957 }
958
returnSharedMemory(const CallbackType &,int64_t)959 ScopedAStatus DefaultVehicleHal::returnSharedMemory(const CallbackType&, int64_t) {
960 // TODO(b/200737967): implement this.
961 return ScopedAStatus::ok();
962 }
963
getHardware()964 IVehicleHardware* DefaultVehicleHal::getHardware() {
965 return mVehicleHardware.get();
966 }
967
checkPermissionHelper(const VehiclePropValue & value,VehiclePropertyAccess accessToTest) const968 VhalResult<void> DefaultVehicleHal::checkPermissionHelper(
969 const VehiclePropValue& value, VehiclePropertyAccess accessToTest) const {
970 static const std::unordered_set<VehiclePropertyAccess> validAccesses = {
971 VehiclePropertyAccess::WRITE, VehiclePropertyAccess::READ,
972 VehiclePropertyAccess::READ_WRITE};
973 if (validAccesses.find(accessToTest) == validAccesses.end()) {
974 return StatusError(StatusCode::INVALID_ARG)
975 << "checkPermissionHelper parameter is an invalid access type";
976 }
977
978 int32_t propId = value.prop;
979 auto result = getConfig(propId);
980 if (!result.ok()) {
981 return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
982 }
983
984 const VehiclePropConfig& config = result.value();
985 const VehicleAreaConfig* areaConfig = getAreaConfig(value, config);
986
987 if (areaConfig == nullptr && !isGlobalProp(propId)) {
988 return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId;
989 }
990 if (!hasRequiredAccess(config.access, accessToTest) &&
991 (areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
992 return StatusError(StatusCode::ACCESS_DENIED)
993 << StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
994 propId, static_cast<int32_t>(accessToTest));
995 }
996 return {};
997 }
998
checkWritePermission(const VehiclePropValue & value) const999 VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
1000 return checkPermissionHelper(value, VehiclePropertyAccess::WRITE);
1001 }
1002
checkReadPermission(const VehiclePropValue & value) const1003 VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
1004 return checkPermissionHelper(value, VehiclePropertyAccess::READ);
1005 }
1006
checkHealth(IVehicleHardware * vehicleHardware,std::weak_ptr<SubscriptionManager> subscriptionManager)1007 void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
1008 std::weak_ptr<SubscriptionManager> subscriptionManager) {
1009 StatusCode status = vehicleHardware->checkHealth();
1010 if (status != StatusCode::OK) {
1011 ALOGE("VHAL check health returns non-okay status");
1012 return;
1013 }
1014 std::vector<VehiclePropValue> values = {{
1015 .areaId = 0,
1016 .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
1017 .status = VehiclePropertyStatus::AVAILABLE,
1018 .value.int64Values = {uptimeMillis()},
1019 }};
1020 onPropertyChangeEvent(subscriptionManager, std::move(values));
1021 return;
1022 }
1023
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)1024 binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath(
1025 AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
1026 return AIBinder_linkToDeath(binder, recipient, cookie);
1027 }
1028
isAlive(const AIBinder * binder)1029 bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) {
1030 return AIBinder_isAlive(binder);
1031 }
1032
setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> handler)1033 void DefaultVehicleHal::setBinderLifecycleHandler(
1034 std::unique_ptr<BinderLifecycleInterface> handler) {
1035 mBinderLifecycleHandler = std::move(handler);
1036 }
1037
checkDumpPermission()1038 bool DefaultVehicleHal::checkDumpPermission() {
1039 uid_t uid = AIBinder_getCallingUid();
1040 return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
1041 }
1042
dump(int fd,const char ** args,uint32_t numArgs)1043 binder_status_t DefaultVehicleHal::dump(int fd, const char** args, uint32_t numArgs) {
1044 if (!checkDumpPermission()) {
1045 dprintf(fd, "Caller must be root, system or shell");
1046 return STATUS_PERMISSION_DENIED;
1047 }
1048
1049 std::vector<std::string> options;
1050 for (uint32_t i = 0; i < numArgs; i++) {
1051 options.push_back(args[i]);
1052 }
1053 if (options.size() == 1 && options[0] == "-a") {
1054 // Ignore "-a" option. Bugreport will call with this option.
1055 options.clear();
1056 }
1057 DumpResult result = mVehicleHardware->dump(options);
1058 if (result.refreshPropertyConfigs) {
1059 getAllPropConfigsFromHardwareLocked();
1060 }
1061 dprintf(fd, "%s", (result.buffer + "\n").c_str());
1062 if (!result.callerShouldDumpState) {
1063 return STATUS_OK;
1064 }
1065 dprintf(fd, "Vehicle HAL State: \n");
1066 std::unordered_map<int32_t, VehiclePropConfig> configsByPropIdCopy;
1067 getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
1068 SharedScopedLockAssertion lockAssertion(mConfigLock);
1069
1070 configsByPropIdCopy = configsByPropId;
1071 });
1072 {
1073 std::scoped_lock<std::mutex> lockGuard(mLock);
1074 dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
1075 dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
1076 dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
1077 dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
1078 dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
1079 }
1080 return STATUS_OK;
1081 }
1082
countSubscribeClients()1083 size_t DefaultVehicleHal::countSubscribeClients() {
1084 return mSubscriptionManager->countClients();
1085 }
1086
1087 } // namespace vehicle
1088 } // namespace automotive
1089 } // namespace hardware
1090 } // namespace android
1091