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