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
26 #include <android-base/result.h>
27 #include <android-base/stringprintf.h>
28 #include <android/binder_ibinder.h>
29 #include <private/android_filesystem_config.h>
30 #include <utils/Log.h>
31 #include <utils/SystemClock.h>
32 #include <utils/Trace.h>
33
34 #include <inttypes.h>
35 #include <set>
36 #include <unordered_set>
37
38 namespace android {
39 namespace hardware {
40 namespace automotive {
41 namespace vehicle {
42
43 namespace {
44
45 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
46 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
47 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
48 using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
49 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
50 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
51 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
52 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
53 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
54 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
55 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
56 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
57 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
58 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
59 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
60 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
61 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
62 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
63 using ::android::automotive::car_binder_lib::LargeParcelableBase;
64 using ::android::base::Error;
65 using ::android::base::expected;
66 using ::android::base::Result;
67 using ::android::base::StringPrintf;
68
69 using ::ndk::ScopedAIBinder_DeathRecipient;
70 using ::ndk::ScopedAStatus;
71
toString(const std::unordered_set<int64_t> & values)72 std::string toString(const std::unordered_set<int64_t>& values) {
73 std::string str = "";
74 for (auto it = values.begin(); it != values.end(); it++) {
75 str += std::to_string(*it);
76 if (std::next(it, 1) != values.end()) {
77 str += ", ";
78 }
79 }
80 return str;
81 }
82
getDefaultSampleRateHz(float sampleRateHz,float minSampleRateHz,float maxSampleRateHz)83 float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) {
84 if (sampleRateHz < minSampleRateHz) {
85 return minSampleRateHz;
86 }
87 if (sampleRateHz > maxSampleRateHz) {
88 return maxSampleRateHz;
89 }
90 return sampleRateHz;
91 }
92
93 } // namespace
94
maybeAddClient(const CallbackType & callback)95 std::shared_ptr<SubscriptionClient> DefaultVehicleHal::SubscriptionClients::maybeAddClient(
96 const CallbackType& callback) {
97 std::scoped_lock<std::mutex> lockGuard(mLock);
98 return getOrCreateClient(&mClients, callback, mPendingRequestPool);
99 }
100
getClient(const CallbackType & callback)101 std::shared_ptr<SubscriptionClient> DefaultVehicleHal::SubscriptionClients::getClient(
102 const CallbackType& callback) {
103 std::scoped_lock<std::mutex> lockGuard(mLock);
104 const AIBinder* clientId = callback->asBinder().get();
105 if (mClients.find(clientId) == mClients.end()) {
106 return nullptr;
107 }
108 return mClients[clientId];
109 }
110
getId(const CallbackType & callback)111 int64_t DefaultVehicleHal::SubscribeIdByClient::getId(const CallbackType& callback) {
112 std::scoped_lock<std::mutex> lockGuard(mLock);
113 // This would be initialized to 0 if callback does not exist in the map.
114 int64_t subscribeId = (mIds[callback->asBinder().get()])++;
115 return subscribeId;
116 }
117
removeClient(const AIBinder * clientId)118 void DefaultVehicleHal::SubscriptionClients::removeClient(const AIBinder* clientId) {
119 std::scoped_lock<std::mutex> lockGuard(mLock);
120 mClients.erase(clientId);
121 }
122
countClients()123 size_t DefaultVehicleHal::SubscriptionClients::countClients() {
124 std::scoped_lock<std::mutex> lockGuard(mLock);
125 return mClients.size();
126 }
127
DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)128 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
129 : mVehicleHardware(std::move(vehicleHardware)),
130 mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
131 if (!getAllPropConfigsFromHardware()) {
132 return;
133 }
134
135 mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool);
136
137 auto subscribeIdByClient = std::make_shared<SubscribeIdByClient>();
138 IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
139 mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
140
141 std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
142 mVehicleHardware->registerOnPropertyChangeEvent(
143 std::make_unique<IVehicleHardware::PropertyChangeCallback>(
144 [subscriptionManagerCopy](std::vector<VehiclePropValue> updatedValues) {
145 onPropertyChangeEvent(subscriptionManagerCopy, updatedValues);
146 }));
147 mVehicleHardware->registerOnPropertySetErrorEvent(
148 std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
149 [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
150 onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
151 }));
152
153 // Register heartbeat event.
154 mRecurrentAction = std::make_shared<std::function<void()>>(
155 [vehicleHardwarePtr, subscriptionManagerCopy]() {
156 checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
157 });
158 mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
159
160 mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
161 mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
162 mDeathRecipient = ScopedAIBinder_DeathRecipient(
163 AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
164 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
165 &DefaultVehicleHal::onBinderUnlinked);
166 }
167
~DefaultVehicleHal()168 DefaultVehicleHal::~DefaultVehicleHal() {
169 // Delete the deathRecipient so that onBinderDied would not be called to reference 'this'.
170 mDeathRecipient = ScopedAIBinder_DeathRecipient();
171 mBinderEvents.deactivate();
172 if (mOnBinderDiedUnlinkedHandlerThread.joinable()) {
173 mOnBinderDiedUnlinkedHandlerThread.join();
174 }
175 // mRecurrentAction uses pointer to mVehicleHardware, so it has to be unregistered before
176 // mVehicleHardware.
177 mRecurrentTimer.unregisterTimerCallback(mRecurrentAction);
178 // mSubscriptionManager uses pointer to mVehicleHardware, so it has to be destroyed before
179 // mVehicleHardware.
180 mSubscriptionManager.reset();
181 mVehicleHardware.reset();
182 }
183
onPropertyChangeEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,const std::vector<VehiclePropValue> & updatedValues)184 void DefaultVehicleHal::onPropertyChangeEvent(
185 const std::weak_ptr<SubscriptionManager>& subscriptionManager,
186 const std::vector<VehiclePropValue>& updatedValues) {
187 auto manager = subscriptionManager.lock();
188 if (manager == nullptr) {
189 ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
190 return;
191 }
192 auto updatedValuesByClients = manager->getSubscribedClients(updatedValues);
193 for (const auto& [callback, valuePtrs] : updatedValuesByClients) {
194 std::vector<VehiclePropValue> values;
195 for (const VehiclePropValue* valuePtr : valuePtrs) {
196 values.push_back(*valuePtr);
197 }
198 SubscriptionClient::sendUpdatedValues(callback, std::move(values));
199 }
200 }
201
onPropertySetErrorEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,const std::vector<SetValueErrorEvent> & errorEvents)202 void DefaultVehicleHal::onPropertySetErrorEvent(
203 const std::weak_ptr<SubscriptionManager>& subscriptionManager,
204 const std::vector<SetValueErrorEvent>& errorEvents) {
205 auto manager = subscriptionManager.lock();
206 if (manager == nullptr) {
207 ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
208 return;
209 }
210 auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents);
211 for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) {
212 SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors));
213 }
214 }
215
216 template <class T>
getOrCreateClient(std::unordered_map<const AIBinder *,std::shared_ptr<T>> * clients,const CallbackType & callback,std::shared_ptr<PendingRequestPool> pendingRequestPool)217 std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
218 std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
219 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
220 const AIBinder* clientId = callback->asBinder().get();
221 if (clients->find(clientId) == clients->end()) {
222 (*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
223 }
224 return (*clients)[clientId];
225 }
226
monitorBinderLifeCycleLocked(const AIBinder * clientId)227 bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) {
228 OnBinderDiedContext* contextPtr = nullptr;
229 if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
230 return mBinderLifecycleHandler->isAlive(clientId);
231 } else {
232 std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
233 OnBinderDiedContext{.vhal = this, .clientId = clientId});
234 // We know context must be alive when we use contextPtr because context would only
235 // be removed in OnBinderUnlinked, which must be called after OnBinderDied.
236 contextPtr = context.get();
237 // Insert into a map to keep the context object alive.
238 mOnBinderDiedContexts[clientId] = std::move(context);
239 }
240
241 // If this function fails, onBinderUnlinked would be called to remove the added context.
242 binder_status_t status = mBinderLifecycleHandler->linkToDeath(
243 const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
244 if (status == STATUS_OK) {
245 return true;
246 }
247 ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
248 static_cast<int>(status));
249 return false;
250 }
251
onBinderDied(void * cookie)252 void DefaultVehicleHal::onBinderDied(void* cookie) {
253 OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
254 // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
255 // thread because we might be holding the mLock the handler requires.
256 context->vhal->mBinderEvents.push(
257 BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId});
258 }
259
onBinderDiedWithContext(const AIBinder * clientId)260 void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) {
261 std::scoped_lock<std::mutex> lockGuard(mLock);
262 ALOGD("binder died, client ID: %p", clientId);
263 mSetValuesClients.erase(clientId);
264 mGetValuesClients.erase(clientId);
265 mSubscriptionClients->removeClient(clientId);
266 mSubscriptionManager->unsubscribe(clientId);
267 }
268
onBinderUnlinked(void * cookie)269 void DefaultVehicleHal::onBinderUnlinked(void* cookie) {
270 OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
271 // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
272 // thread because we might be holding the mLock the handler requires.
273 context->vhal->mBinderEvents.push(
274 BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId});
275 }
276
onBinderUnlinkedWithContext(const AIBinder * clientId)277 void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) {
278 ALOGD("binder unlinked");
279 std::scoped_lock<std::mutex> lockGuard(mLock);
280 // Delete the context associated with this cookie.
281 mOnBinderDiedContexts.erase(clientId);
282 }
283
onBinderDiedUnlinkedHandler()284 void DefaultVehicleHal::onBinderDiedUnlinkedHandler() {
285 while (mBinderEvents.waitForItems()) {
286 for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) {
287 if (event.forOnBinderDied) {
288 onBinderDiedWithContext(event.clientId);
289 } else {
290 onBinderUnlinkedWithContext(event.clientId);
291 }
292 }
293 }
294 }
295
296 template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
297 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
298 std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
299 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
300 template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
301 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
302 std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
303 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
304 template std::shared_ptr<SubscriptionClient>
305 DefaultVehicleHal::getOrCreateClient<SubscriptionClient>(
306 std::unordered_map<const AIBinder*, std::shared_ptr<SubscriptionClient>>* clients,
307 const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
308
setTimeout(int64_t timeoutInNano)309 void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
310 mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
311 }
312
getAllPropConfigsFromHardware()313 bool DefaultVehicleHal::getAllPropConfigsFromHardware() {
314 auto configs = mVehicleHardware->getAllPropertyConfigs();
315 for (auto& config : configs) {
316 mConfigsByPropId[config.prop] = config;
317 }
318 VehiclePropConfigs vehiclePropConfigs;
319 vehiclePropConfigs.payloads = std::move(configs);
320 auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
321 if (!result.ok()) {
322 ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
323 result.error().message().c_str(), static_cast<int>(result.error().code()));
324 mConfigFile = nullptr;
325 return false;
326 }
327
328 if (result.value() != nullptr) {
329 mConfigFile = std::move(result.value());
330 }
331 return true;
332 }
333
getAllPropConfigs(VehiclePropConfigs * output)334 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
335 if (mConfigFile != nullptr) {
336 output->payloads.clear();
337 output->sharedMemoryFd.set(dup(mConfigFile->get()));
338 return ScopedAStatus::ok();
339 }
340 output->payloads.reserve(mConfigsByPropId.size());
341 for (const auto& [_, config] : mConfigsByPropId) {
342 output->payloads.push_back(config);
343 }
344 return ScopedAStatus::ok();
345 }
346
getConfig(int32_t propId) const347 Result<const VehiclePropConfig*> DefaultVehicleHal::getConfig(int32_t propId) const {
348 auto it = mConfigsByPropId.find(propId);
349 if (it == mConfigsByPropId.end()) {
350 return Error() << "no config for property, ID: " << propId;
351 }
352 return &(it->second);
353 }
354
checkProperty(const VehiclePropValue & propValue)355 Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
356 int32_t propId = propValue.prop;
357 auto result = getConfig(propId);
358 if (!result.ok()) {
359 return result.error();
360 }
361 const VehiclePropConfig* config = result.value();
362 const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, *config);
363 if (!isGlobalProp(propId) && areaConfig == nullptr) {
364 // Ignore areaId for global property. For non global property, check whether areaId is
365 // allowed. areaId must appear in areaConfig.
366 return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
367 << ", not listed in config";
368 }
369 if (auto result = checkPropValue(propValue, config); !result.ok()) {
370 return Error() << "invalid property value: " << propValue.toString()
371 << ", error: " << getErrorMsg(result);
372 }
373 if (auto result = checkValueRange(propValue, areaConfig); !result.ok()) {
374 return Error() << "property value out of range: " << propValue.toString()
375 << ", error: " << getErrorMsg(result);
376 }
377 return {};
378 }
379
getValues(const CallbackType & callback,const GetValueRequests & requests)380 ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
381 const GetValueRequests& requests) {
382 ATRACE_CALL();
383 if (callback == nullptr) {
384 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
385 }
386 expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
387 deserializedResults = fromStableLargeParcelable(requests);
388 if (!deserializedResults.ok()) {
389 ALOGE("getValues: failed to parse getValues requests");
390 return std::move(deserializedResults.error());
391 }
392 const std::vector<GetValueRequest>& getValueRequests =
393 deserializedResults.value().getObject()->payloads;
394
395 auto maybeRequestIds = checkDuplicateRequests(getValueRequests);
396 if (!maybeRequestIds.ok()) {
397 ALOGE("getValues: duplicate request ID");
398 return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
399 }
400
401 // A list of failed result we already know before sending to hardware.
402 std::vector<GetValueResult> failedResults;
403 // The list of requests that we would send to hardware.
404 std::vector<GetValueRequest> hardwareRequests;
405
406 for (const auto& request : getValueRequests) {
407 if (auto result = checkReadPermission(request.prop); !result.ok()) {
408 ALOGW("property does not support reading: %s", getErrorMsg(result).c_str());
409 failedResults.push_back(GetValueResult{
410 .requestId = request.requestId,
411 .status = getErrorCode(result),
412 .prop = {},
413 });
414 } else {
415 hardwareRequests.push_back(request);
416 }
417 }
418
419 // The set of request Ids that we would send to hardware.
420 std::unordered_set<int64_t> hardwareRequestIds;
421 for (const auto& request : hardwareRequests) {
422 hardwareRequestIds.insert(request.requestId);
423 }
424
425 std::shared_ptr<GetValuesClient> client;
426 {
427 // Lock to make sure onBinderDied would not be called concurrently.
428 std::scoped_lock lockGuard(mLock);
429 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
430 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
431 "client died");
432 }
433
434 client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
435 }
436
437 // Register the pending hardware requests and also check for duplicate request Ids.
438 if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
439 ALOGE("getValues[%s]: failed to add pending requests, error: %s",
440 toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
441 return toScopedAStatus(addRequestResult);
442 }
443
444 if (!failedResults.empty()) {
445 // First send the failed results we already know back to the client.
446 client->sendResults(std::move(failedResults));
447 }
448
449 if (hardwareRequests.empty()) {
450 return ScopedAStatus::ok();
451 }
452
453 if (StatusCode status =
454 mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests);
455 status != StatusCode::OK) {
456 // If the hardware returns error, finish all the pending requests for this request because
457 // we never expect hardware to call callback for these requests.
458 client->tryFinishRequests(hardwareRequestIds);
459 ALOGE("getValues[%s]: failed to get value from VehicleHardware, status: %d",
460 toString(hardwareRequestIds).c_str(), toInt(status));
461 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
462 toInt(status), "failed to get value from VehicleHardware");
463 }
464 return ScopedAStatus::ok();
465 }
466
setValues(const CallbackType & callback,const SetValueRequests & requests)467 ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
468 const SetValueRequests& requests) {
469 ATRACE_CALL();
470 if (callback == nullptr) {
471 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
472 }
473 expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
474 deserializedResults = fromStableLargeParcelable(requests);
475 if (!deserializedResults.ok()) {
476 ALOGE("setValues: failed to parse setValues requests");
477 return std::move(deserializedResults.error());
478 }
479 const std::vector<SetValueRequest>& setValueRequests =
480 deserializedResults.value().getObject()->payloads;
481
482 // A list of failed result we already know before sending to hardware.
483 std::vector<SetValueResult> failedResults;
484 // The list of requests that we would send to hardware.
485 std::vector<SetValueRequest> hardwareRequests;
486
487 auto maybeRequestIds = checkDuplicateRequests(setValueRequests);
488 if (!maybeRequestIds.ok()) {
489 ALOGE("setValues: duplicate request ID");
490 return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
491 }
492
493 for (auto& request : setValueRequests) {
494 int64_t requestId = request.requestId;
495 if (auto result = checkWritePermission(request.value); !result.ok()) {
496 ALOGW("property does not support writing: %s", getErrorMsg(result).c_str());
497 failedResults.push_back(SetValueResult{
498 .requestId = requestId,
499 .status = getErrorCode(result),
500 });
501 continue;
502 }
503 if (auto result = checkProperty(request.value); !result.ok()) {
504 ALOGW("setValues[%" PRId64 "]: property is not valid: %s", requestId,
505 getErrorMsg(result).c_str());
506 failedResults.push_back(SetValueResult{
507 .requestId = requestId,
508 .status = StatusCode::INVALID_ARG,
509 });
510 continue;
511 }
512
513 hardwareRequests.push_back(request);
514 }
515
516 // The set of request Ids that we would send to hardware.
517 std::unordered_set<int64_t> hardwareRequestIds;
518 for (const auto& request : hardwareRequests) {
519 hardwareRequestIds.insert(request.requestId);
520 }
521
522 std::shared_ptr<SetValuesClient> client;
523 {
524 // Lock to make sure onBinderDied would not be called concurrently.
525 std::scoped_lock lockGuard(mLock);
526 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
527 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
528 "client died");
529 }
530 client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
531 }
532
533 // Register the pending hardware requests and also check for duplicate request Ids.
534 if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
535 ALOGE("setValues[%s], failed to add pending requests, error: %s",
536 toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
537 return toScopedAStatus(addRequestResult);
538 }
539
540 if (!failedResults.empty()) {
541 // First send the failed results we already know back to the client.
542 client->sendResults(std::move(failedResults));
543 }
544
545 if (hardwareRequests.empty()) {
546 return ScopedAStatus::ok();
547 }
548
549 if (StatusCode status =
550 mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
551 status != StatusCode::OK) {
552 // If the hardware returns error, finish all the pending requests for this request because
553 // we never expect hardware to call callback for these requests.
554 client->tryFinishRequests(hardwareRequestIds);
555 ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d",
556 toString(hardwareRequestIds).c_str(), toInt(status));
557 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
558 toInt(status), "failed to set value to VehicleHardware");
559 }
560
561 return ScopedAStatus::ok();
562 }
563
564 #define CHECK_DUPLICATE_REQUESTS(PROP_NAME) \
565 do { \
566 std::vector<int64_t> requestIds; \
567 std::set<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> requestProps; \
568 for (const auto& request : requests) { \
569 const auto& prop = request.PROP_NAME; \
570 if (requestProps.count(prop) != 0) { \
571 return ::android::base::Error() \
572 << "duplicate request for property: " << prop.toString(); \
573 } \
574 requestProps.insert(prop); \
575 requestIds.push_back(request.requestId); \
576 } \
577 return requestIds; \
578 } while (0);
579
checkDuplicateRequests(const std::vector<GetValueRequest> & requests)580 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
581 const std::vector<GetValueRequest>& requests) {
582 CHECK_DUPLICATE_REQUESTS(prop);
583 }
584
checkDuplicateRequests(const std::vector<SetValueRequest> & requests)585 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
586 const std::vector<SetValueRequest>& requests) {
587 CHECK_DUPLICATE_REQUESTS(value);
588 }
589
590 #undef CHECK_DUPLICATE_REQUESTS
591
getPropConfigs(const std::vector<int32_t> & props,VehiclePropConfigs * output)592 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
593 VehiclePropConfigs* output) {
594 std::vector<VehiclePropConfig> configs;
595 for (int32_t prop : props) {
596 if (mConfigsByPropId.find(prop) != mConfigsByPropId.end()) {
597 configs.push_back(mConfigsByPropId[prop]);
598 } else {
599 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
600 toInt(StatusCode::INVALID_ARG),
601 StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
602 }
603 }
604 return vectorToStableLargeParcelable(std::move(configs), output);
605 }
606
checkSubscribeOptions(const std::vector<SubscribeOptions> & options)607 VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
608 const std::vector<SubscribeOptions>& options) {
609 for (const auto& option : options) {
610 int32_t propId = option.propId;
611 if (mConfigsByPropId.find(propId) == mConfigsByPropId.end()) {
612 return StatusError(StatusCode::INVALID_ARG)
613 << StringPrintf("no config for property, ID: %" PRId32, propId);
614 }
615 const VehiclePropConfig& config = mConfigsByPropId[propId];
616
617 if (config.changeMode != VehiclePropertyChangeMode::ON_CHANGE &&
618 config.changeMode != VehiclePropertyChangeMode::CONTINUOUS) {
619 return StatusError(StatusCode::INVALID_ARG)
620 << "only support subscribing to ON_CHANGE or CONTINUOUS property";
621 }
622
623 if (config.access != VehiclePropertyAccess::READ &&
624 config.access != VehiclePropertyAccess::READ_WRITE) {
625 return StatusError(StatusCode::ACCESS_DENIED)
626 << StringPrintf("Property %" PRId32 " has no read access", propId);
627 }
628
629 if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
630 float sampleRateHz = option.sampleRate;
631 float minSampleRateHz = config.minSampleRate;
632 float maxSampleRateHz = config.maxSampleRate;
633 float defaultRateHz =
634 getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz);
635 if (sampleRateHz != defaultRateHz) {
636 ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f "
637 "HZ",
638 sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz);
639 sampleRateHz = defaultRateHz;
640 }
641 if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) {
642 return StatusError(StatusCode::INVALID_ARG)
643 << "invalid sample rate: " << sampleRateHz << " HZ";
644 }
645 }
646
647 if (isGlobalProp(propId)) {
648 continue;
649 }
650
651 // Non-global property.
652 for (int32_t areaId : option.areaIds) {
653 if (auto areaConfig = getAreaConfig(propId, areaId, config); areaConfig == nullptr) {
654 return StatusError(StatusCode::INVALID_ARG)
655 << StringPrintf("invalid area ID: %" PRId32 " for prop ID: %" PRId32
656 ", not listed in config",
657 areaId, propId);
658 }
659 }
660 }
661 return {};
662 }
663
subscribe(const CallbackType & callback,const std::vector<SubscribeOptions> & options,int32_t maxSharedMemoryFileCount)664 ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
665 const std::vector<SubscribeOptions>& options,
666 [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
667 // TODO(b/205189110): Use shared memory file count.
668 if (callback == nullptr) {
669 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
670 }
671 if (auto result = checkSubscribeOptions(options); !result.ok()) {
672 ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
673 return toScopedAStatus(result);
674 }
675 std::vector<SubscribeOptions> onChangeSubscriptions;
676 std::vector<SubscribeOptions> continuousSubscriptions;
677 for (const auto& option : options) {
678 int32_t propId = option.propId;
679 // We have already validate config exists.
680 const VehiclePropConfig& config = mConfigsByPropId[propId];
681
682 SubscribeOptions optionCopy = option;
683 // If areaIds is empty, subscribe to all areas.
684 if (optionCopy.areaIds.empty() && !isGlobalProp(propId)) {
685 for (const auto& areaConfig : config.areaConfigs) {
686 optionCopy.areaIds.push_back(areaConfig.areaId);
687 }
688 }
689
690 if (isGlobalProp(propId)) {
691 optionCopy.areaIds = {0};
692 }
693
694 if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
695 optionCopy.sampleRate = getDefaultSampleRateHz(
696 optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate);
697 continuousSubscriptions.push_back(std::move(optionCopy));
698 } else {
699 onChangeSubscriptions.push_back(std::move(optionCopy));
700 }
701 }
702
703 {
704 // Lock to make sure onBinderDied would not be called concurrently.
705 std::scoped_lock lockGuard(mLock);
706 if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
707 return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
708 "client died");
709 }
710
711 // Create a new SubscriptionClient if there isn't an existing one.
712 mSubscriptionClients->maybeAddClient(callback);
713
714 if (!onChangeSubscriptions.empty()) {
715 auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
716 /*isContinuousProperty=*/false);
717 if (!result.ok()) {
718 return toScopedAStatus(result);
719 }
720 }
721 if (!continuousSubscriptions.empty()) {
722 auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions,
723 /*isContinuousProperty=*/true);
724 if (!result.ok()) {
725 return toScopedAStatus(result);
726 }
727 }
728 }
729 return ScopedAStatus::ok();
730 }
731
unsubscribe(const CallbackType & callback,const std::vector<int32_t> & propIds)732 ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType& callback,
733 const std::vector<int32_t>& propIds) {
734 if (callback == nullptr) {
735 return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
736 }
737 return toScopedAStatus(mSubscriptionManager->unsubscribe(callback->asBinder().get(), propIds));
738 }
739
returnSharedMemory(const CallbackType &,int64_t)740 ScopedAStatus DefaultVehicleHal::returnSharedMemory(const CallbackType&, int64_t) {
741 // TODO(b/200737967): implement this.
742 return ScopedAStatus::ok();
743 }
744
getHardware()745 IVehicleHardware* DefaultVehicleHal::getHardware() {
746 return mVehicleHardware.get();
747 }
748
checkWritePermission(const VehiclePropValue & value) const749 VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
750 int32_t propId = value.prop;
751 auto result = getConfig(propId);
752 if (!result.ok()) {
753 return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
754 }
755 const VehiclePropConfig* config = result.value();
756
757 if (config->access != VehiclePropertyAccess::WRITE &&
758 config->access != VehiclePropertyAccess::READ_WRITE) {
759 return StatusError(StatusCode::ACCESS_DENIED)
760 << StringPrintf("Property %" PRId32 " has no write access", propId);
761 }
762 return {};
763 }
764
checkReadPermission(const VehiclePropValue & value) const765 VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
766 int32_t propId = value.prop;
767 auto result = getConfig(propId);
768 if (!result.ok()) {
769 return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
770 }
771 const VehiclePropConfig* config = result.value();
772
773 if (config->access != VehiclePropertyAccess::READ &&
774 config->access != VehiclePropertyAccess::READ_WRITE) {
775 return StatusError(StatusCode::ACCESS_DENIED)
776 << StringPrintf("Property %" PRId32 " has no read access", propId);
777 }
778 return {};
779 }
780
checkHealth(IVehicleHardware * vehicleHardware,std::weak_ptr<SubscriptionManager> subscriptionManager)781 void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
782 std::weak_ptr<SubscriptionManager> subscriptionManager) {
783 StatusCode status = vehicleHardware->checkHealth();
784 if (status != StatusCode::OK) {
785 ALOGE("VHAL check health returns non-okay status");
786 return;
787 }
788 std::vector<VehiclePropValue> values = {{
789 .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
790 .areaId = 0,
791 .status = VehiclePropertyStatus::AVAILABLE,
792 .value.int64Values = {uptimeMillis()},
793 }};
794 onPropertyChangeEvent(subscriptionManager, values);
795 return;
796 }
797
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)798 binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath(
799 AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
800 return AIBinder_linkToDeath(binder, recipient, cookie);
801 }
802
isAlive(const AIBinder * binder)803 bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) {
804 return AIBinder_isAlive(binder);
805 }
806
setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> handler)807 void DefaultVehicleHal::setBinderLifecycleHandler(
808 std::unique_ptr<BinderLifecycleInterface> handler) {
809 mBinderLifecycleHandler = std::move(handler);
810 }
811
checkDumpPermission()812 bool DefaultVehicleHal::checkDumpPermission() {
813 uid_t uid = AIBinder_getCallingUid();
814 return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
815 }
816
dump(int fd,const char ** args,uint32_t numArgs)817 binder_status_t DefaultVehicleHal::dump(int fd, const char** args, uint32_t numArgs) {
818 if (!checkDumpPermission()) {
819 dprintf(fd, "Caller must be root, system or shell");
820 return STATUS_PERMISSION_DENIED;
821 }
822
823 std::vector<std::string> options;
824 for (uint32_t i = 0; i < numArgs; i++) {
825 options.push_back(args[i]);
826 }
827 if (options.size() == 1 && options[0] == "-a") {
828 // Ignore "-a" option. Bugreport will call with this option.
829 options.clear();
830 }
831 DumpResult result = mVehicleHardware->dump(options);
832 if (result.refreshPropertyConfigs) {
833 getAllPropConfigsFromHardware();
834 }
835 dprintf(fd, "%s", (result.buffer + "\n").c_str());
836 if (!result.callerShouldDumpState) {
837 return STATUS_OK;
838 }
839 dprintf(fd, "Vehicle HAL State: \n");
840 {
841 std::scoped_lock<std::mutex> lockGuard(mLock);
842 dprintf(fd, "Containing %zu property configs\n", mConfigsByPropId.size());
843 dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
844 dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
845 dprintf(fd, "Currently have %zu subscription clients\n",
846 mSubscriptionClients->countClients());
847 }
848 return STATUS_OK;
849 }
850
851 } // namespace vehicle
852 } // namespace automotive
853 } // namespace hardware
854 } // namespace android
855