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