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