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