• 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::HasSupportedValueInfo;
53 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
54 using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResult;
55 using ::aidl::android::hardware::automotive::vehicle::MinMaxSupportedValueResults;
56 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
57 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
58 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
59 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
60 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
61 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
62 using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResult;
63 using ::aidl::android::hardware::automotive::vehicle::SupportedValuesListResults;
64 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
65 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
66 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
67 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
68 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
69 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
70 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
71 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
72 using ::aidl::android::hardware::automotive::vehicle::VersionForVehicleProperty;
73 using ::android::automotive::car_binder_lib::LargeParcelableBase;
74 using ::android::base::Error;
75 using ::android::base::expected;
76 using ::android::base::Result;
77 using ::android::base::StringPrintf;
78 
79 using ::ndk::ScopedAIBinder_DeathRecipient;
80 using ::ndk::ScopedAStatus;
81 using ::ndk::ScopedFileDescriptor;
82 
83 using VhalPropIdAreaId = ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;
84 
toString(const std::unordered_set<int64_t> & values)85 std::string toString(const std::unordered_set<int64_t>& values) {
86     std::string str = "";
87     for (auto it = values.begin(); it != values.end(); it++) {
88         str += std::to_string(*it);
89         if (std::next(it, 1) != values.end()) {
90             str += ", ";
91         }
92     }
93     return str;
94 }
95 
getDefaultSampleRateHz(float sampleRateHz,float minSampleRateHz,float maxSampleRateHz)96 float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) {
97     if (sampleRateHz < minSampleRateHz) {
98         return minSampleRateHz;
99     }
100     if (sampleRateHz > maxSampleRateHz) {
101         return maxSampleRateHz;
102     }
103     return sampleRateHz;
104 }
105 
106 class SCOPED_CAPABILITY SharedScopedLockAssertion {
107   public:
ACQUIRE_SHARED(mutex)108     SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {}
RELEASE()109     ~SharedScopedLockAssertion() RELEASE() {}
110 };
111 
112 class SCOPED_CAPABILITY UniqueScopedLockAssertion {
113   public:
ACQUIRE(mutex)114     UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {}
RELEASE()115     ~UniqueScopedLockAssertion() RELEASE() {}
116 };
117 
118 }  // namespace
119 
DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)120 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
121     : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0) {};
122 
DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,int32_t testInterfaceVersion)123 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
124                                      int32_t testInterfaceVersion)
125     : mVehicleHardware(std::move(vehicleHardware)),
126       mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
127       mTestInterfaceVersion(testInterfaceVersion) {
128     ALOGD("DefaultVehicleHal init");
129     IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
130     mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
131     mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
132     if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
133         mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
134         mPropertyChangeEventsBatchingConsumer =
135                 std::make_shared<BatchingConsumer<VehiclePropValue>>();
136         mPropertyChangeEventsBatchingConsumer->run(
137                 mBatchedEventQueue.get(), mEventBatchingWindow,
138                 [this](std::vector<VehiclePropValue> batchedEvents) {
139                     handleBatchedPropertyEvents(std::move(batchedEvents));
140                 });
141     }
142 
143     std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
144     std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
145     std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
146     mVehicleHardware->registerOnPropertyChangeEvent(
147             std::make_unique<IVehicleHardware::PropertyChangeCallback>(
148                     [subscriptionManagerCopy, batchedEventQueueCopy,
149                      eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
150                         if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
151                             batchPropertyChangeEvent(batchedEventQueueCopy,
152                                                      std::move(updatedValues));
153                         } else {
154                             onPropertyChangeEvent(subscriptionManagerCopy,
155                                                   std::move(updatedValues));
156                         }
157                     }));
158     mVehicleHardware->registerOnPropertySetErrorEvent(
159             std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
160                     [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
161                         onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
162                     }));
163     mVehicleHardware->registerSupportedValueChangeCallback(
164             std::make_unique<IVehicleHardware::SupportedValueChangeCallback>(
165                     [subscriptionManagerCopy](std::vector<PropIdAreaId> propIdAreaIds) {
166                         onSupportedValueChange(subscriptionManagerCopy, propIdAreaIds);
167                     }));
168 
169     // Register heartbeat event.
170     mRecurrentAction = std::make_shared<std::function<void()>>(
171             [vehicleHardwarePtr, subscriptionManagerCopy]() {
172                 checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
173             });
174     mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
175 
176     mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
177     mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
178     mDeathRecipient = ScopedAIBinder_DeathRecipient(
179             AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
180     AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
181                                           &DefaultVehicleHal::onBinderUnlinked);
182 }
183 
~DefaultVehicleHal()184 DefaultVehicleHal::~DefaultVehicleHal() {
185     // Delete the deathRecipient so that onBinderDied would not be called to reference 'this'.
186     mDeathRecipient = ScopedAIBinder_DeathRecipient();
187     mBinderEvents.deactivate();
188     if (mOnBinderDiedUnlinkedHandlerThread.joinable()) {
189         mOnBinderDiedUnlinkedHandlerThread.join();
190     }
191     // mRecurrentAction uses pointer to mVehicleHardware, so it has to be unregistered before
192     // mVehicleHardware.
193     mRecurrentTimer.unregisterTimerCallback(mRecurrentAction);
194 
195     if (mBatchedEventQueue) {
196         // mPropertyChangeEventsBatchingConsumer uses mSubscriptionManager and mBatchedEventQueue.
197         mBatchedEventQueue->deactivate();
198         mPropertyChangeEventsBatchingConsumer->requestStop();
199         mPropertyChangeEventsBatchingConsumer->waitStopped();
200         mPropertyChangeEventsBatchingConsumer.reset();
201         mBatchedEventQueue.reset();
202     }
203 
204     // mSubscriptionManager uses pointer to mVehicleHardware, so it has to be destroyed before
205     // mVehicleHardware.
206     mSubscriptionManager.reset();
207     mVehicleHardware.reset();
208 }
209 
batchPropertyChangeEvent(const std::weak_ptr<ConcurrentQueue<VehiclePropValue>> & batchedEventQueue,std::vector<VehiclePropValue> && updatedValues)210 void DefaultVehicleHal::batchPropertyChangeEvent(
211         const std::weak_ptr<ConcurrentQueue<VehiclePropValue>>& batchedEventQueue,
212         std::vector<VehiclePropValue>&& updatedValues) {
213     auto batchedEventQueueStrong = batchedEventQueue.lock();
214     if (batchedEventQueueStrong == nullptr) {
215         ALOGW("%s: the batched property events queue is destroyed, DefaultVehicleHal is ending",
216               __func__);
217         return;
218     }
219     batchedEventQueueStrong->push(std::move(updatedValues));
220 }
221 
handleBatchedPropertyEvents(std::vector<VehiclePropValue> && batchedEvents)222 void DefaultVehicleHal::handleBatchedPropertyEvents(std::vector<VehiclePropValue>&& batchedEvents) {
223     onPropertyChangeEvent(mSubscriptionManager, std::move(batchedEvents));
224 }
225 
onPropertyChangeEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,std::vector<VehiclePropValue> && updatedValues)226 void DefaultVehicleHal::onPropertyChangeEvent(
227         const std::weak_ptr<SubscriptionManager>& subscriptionManager,
228         std::vector<VehiclePropValue>&& updatedValues) {
229     ATRACE_CALL();
230     auto manager = subscriptionManager.lock();
231     if (manager == nullptr) {
232         ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
233         return;
234     }
235     auto updatedValuesByClients = manager->getSubscribedClients(std::move(updatedValues));
236     for (auto& [callback, values] : updatedValuesByClients) {
237         SubscriptionClient::sendUpdatedValues(callback, std::move(values));
238     }
239 }
240 
onPropertySetErrorEvent(const std::weak_ptr<SubscriptionManager> & subscriptionManager,const std::vector<SetValueErrorEvent> & errorEvents)241 void DefaultVehicleHal::onPropertySetErrorEvent(
242         const std::weak_ptr<SubscriptionManager>& subscriptionManager,
243         const std::vector<SetValueErrorEvent>& errorEvents) {
244     auto manager = subscriptionManager.lock();
245     if (manager == nullptr) {
246         ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
247         return;
248     }
249     auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents);
250     for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) {
251         SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors));
252     }
253 }
254 
onSupportedValueChange(const std::weak_ptr<SubscriptionManager> & subscriptionManager,const std::vector<PropIdAreaId> & propIdAreaIds)255 void DefaultVehicleHal::onSupportedValueChange(
256         const std::weak_ptr<SubscriptionManager>& subscriptionManager,
257         const std::vector<PropIdAreaId>& propIdAreaIds) {
258     auto manager = subscriptionManager.lock();
259     if (manager == nullptr) {
260         ALOGW("%s: the SubscriptionManager is destroyed, DefaultVehicleHal is ending", __func__);
261         return;
262     }
263     auto updatedPropIdAreaIdsByClient =
264             manager->getSubscribedClientsForSupportedValueChange(propIdAreaIds);
265     for (auto& [callback, updatedPropIdAreaIds] : updatedPropIdAreaIdsByClient) {
266         SubscriptionClient::sendSupportedValueChangeEvents(callback, updatedPropIdAreaIds);
267     }
268 }
269 
270 template <class T>
getOrCreateClient(std::unordered_map<const AIBinder *,std::shared_ptr<T>> * clients,const CallbackType & callback,std::shared_ptr<PendingRequestPool> pendingRequestPool)271 std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
272         std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
273         const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
274     const AIBinder* clientId = callback->asBinder().get();
275     if (clients->find(clientId) == clients->end()) {
276         (*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
277     }
278     return (*clients)[clientId];
279 }
280 
monitorBinderLifeCycleLocked(const AIBinder * clientId)281 bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) {
282     OnBinderDiedContext* contextPtr = nullptr;
283     if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
284         return mBinderLifecycleHandler->isAlive(clientId);
285     } else {
286         std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
287                 OnBinderDiedContext{.vhal = this, .clientId = clientId});
288         // We know context must be alive when we use contextPtr because context would only
289         // be removed in OnBinderUnlinked, which must be called after OnBinderDied.
290         contextPtr = context.get();
291         // Insert into a map to keep the context object alive.
292         mOnBinderDiedContexts[clientId] = std::move(context);
293     }
294 
295     // If this function fails, onBinderUnlinked would be called to remove the added context.
296     binder_status_t status = mBinderLifecycleHandler->linkToDeath(
297             const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
298     if (status == STATUS_OK) {
299         return true;
300     }
301     ALOGE("failed to call linkToDeath on client binder, client may already died, status: %d",
302           static_cast<int>(status));
303     return false;
304 }
305 
onBinderDied(void * cookie)306 void DefaultVehicleHal::onBinderDied(void* cookie) {
307     OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
308     // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
309     // thread because we might be holding the mLock the handler requires.
310     context->vhal->mBinderEvents.push(
311             BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId});
312 }
313 
onBinderDiedWithContext(const AIBinder * clientId)314 void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) {
315     std::scoped_lock<std::mutex> lockGuard(mLock);
316     ALOGD("binder died, client ID: %p", clientId);
317     mSetValuesClients.erase(clientId);
318     mGetValuesClients.erase(clientId);
319     mSubscriptionManager->unsubscribe(clientId);
320 }
321 
onBinderUnlinked(void * cookie)322 void DefaultVehicleHal::onBinderUnlinked(void* cookie) {
323     OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
324     // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
325     // thread because we might be holding the mLock the handler requires.
326     context->vhal->mBinderEvents.push(
327             BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId});
328 }
329 
onBinderUnlinkedWithContext(const AIBinder * clientId)330 void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) {
331     ALOGD("binder unlinked");
332     std::scoped_lock<std::mutex> lockGuard(mLock);
333     // Delete the context associated with this cookie.
334     mOnBinderDiedContexts.erase(clientId);
335 }
336 
onBinderDiedUnlinkedHandler()337 void DefaultVehicleHal::onBinderDiedUnlinkedHandler() {
338     while (mBinderEvents.waitForItems()) {
339         for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) {
340             if (event.forOnBinderDied) {
341                 onBinderDiedWithContext(event.clientId);
342             } else {
343                 onBinderUnlinkedWithContext(event.clientId);
344             }
345         }
346     }
347 }
348 
349 template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
350 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
351         std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>>* clients,
352         const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
353 template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
354 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
355         std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
356         const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
357 
setTimeout(int64_t timeoutInNano)358 void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
359     mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
360 }
361 
getVhalInterfaceVersion() const362 int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
363     if (mTestInterfaceVersion != 0) {
364         return mTestInterfaceVersion;
365     }
366     int32_t myVersion = 0;
367     // getInterfaceVersion is in-reality a const method.
368     const_cast<DefaultVehicleHal*>(this)->getInterfaceVersion(&myVersion);
369     return myVersion;
370 }
371 
isConfigSupportedForCurrentVhalVersion(const VehiclePropConfig & config) const372 bool DefaultVehicleHal::isConfigSupportedForCurrentVhalVersion(
373         const VehiclePropConfig& config) const {
374     int32_t myVersion = getVhalInterfaceVersion();
375     if (!isSystemProp(config.prop)) {
376         return true;
377     }
378     VehicleProperty property = static_cast<VehicleProperty>(config.prop);
379     std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
380     auto it = VersionForVehicleProperty.find(property);
381     if (it == VersionForVehicleProperty.end()) {
382         ALOGE("The property: %s is not a supported system property, ignore", propertyName.c_str());
383         return false;
384     }
385     int requiredVersion = it->second;
386     if (myVersion < requiredVersion) {
387         ALOGE("The property: %s is not supported for current client VHAL version, "
388               "require %d, current version: %d, ignore",
389               propertyName.c_str(), requiredVersion, myVersion);
390         return false;
391     }
392     return true;
393 }
394 
getAllPropConfigsFromHardwareLocked() const395 bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
396     ALOGD("Get all property configs from hardware");
397     auto configs = mVehicleHardware->getAllPropertyConfigs();
398     std::vector<VehiclePropConfig> filteredConfigs;
399     for (const auto& config : configs) {
400         if (isConfigSupportedForCurrentVhalVersion(config)) {
401             filteredConfigs.push_back(std::move(config));
402         }
403     }
404 
405     {
406         std::unique_lock<std::shared_timed_mutex> configWriteLock(mConfigLock);
407         UniqueScopedLockAssertion lockAssertion(mConfigLock);
408 
409         for (auto& config : filteredConfigs) {
410             mConfigsByPropId[config.prop] = config;
411         }
412         VehiclePropConfigs vehiclePropConfigs;
413         vehiclePropConfigs.payloads = std::move(filteredConfigs);
414         auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
415         if (!result.ok()) {
416             ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
417                   result.error().message().c_str(), static_cast<int>(result.error().code()));
418             mConfigFile = nullptr;
419             return false;
420         }
421 
422         if (result.value() != nullptr) {
423             mConfigFile = std::move(result.value());
424         }
425     }
426 
427     mConfigInit = true;
428     return true;
429 }
430 
getConfigsByPropId(std::function<void (const std::unordered_map<int32_t,VehiclePropConfig> &)> callback) const431 void DefaultVehicleHal::getConfigsByPropId(
432         std::function<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
433     if (!mConfigInit) {
434         CHECK(getAllPropConfigsFromHardwareLocked())
435                 << "Failed to get property configs from hardware";
436     }
437 
438     std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
439     SharedScopedLockAssertion lockAssertion(mConfigLock);
440 
441     callback(mConfigsByPropId);
442 }
443 
getAllPropConfigs(VehiclePropConfigs * output)444 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
445     if (!mConfigInit) {
446         CHECK(getAllPropConfigsFromHardwareLocked())
447                 << "Failed to get property configs from hardware";
448     }
449 
450     std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
451     SharedScopedLockAssertion lockAssertion(mConfigLock);
452 
453     if (mConfigFile != nullptr) {
454         output->payloads.clear();
455         output->sharedMemoryFd.set(dup(mConfigFile->get()));
456         return ScopedAStatus::ok();
457     }
458 
459     output->payloads.reserve(mConfigsByPropId.size());
460     for (const auto& [_, config] : mConfigsByPropId) {
461         output->payloads.push_back(config);
462     }
463     return ScopedAStatus::ok();
464 }
465 
getConfig(int32_t propId) const466 Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
467     Result<VehiclePropConfig> result;
468 
469     if (!mConfigInit) {
470         std::optional<VehiclePropConfig> config = mVehicleHardware->getPropertyConfig(propId);
471         if (!config.has_value()) {
472             return Error() << "no config for property, ID: " << propId;
473         }
474         if (!isConfigSupportedForCurrentVhalVersion(config.value())) {
475             return Error() << "property not supported for current VHAL interface, ID: " << propId;
476         }
477 
478         return config.value();
479     }
480 
481     getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
482         SharedScopedLockAssertion lockAssertion(mConfigLock);
483 
484         auto it = configsByPropId.find(propId);
485         if (it == configsByPropId.end()) {
486             result = Error() << "no config for property, ID: " << propId;
487             return;
488         }
489         // Copy the VehiclePropConfig
490         result = it->second;
491     });
492     return result;
493 }
494 
checkProperty(const VehiclePropValue & propValue)495 Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
496     int32_t propId = propValue.prop;
497     auto result = getConfig(propId);
498     if (!result.ok()) {
499         return result.error();
500     }
501     const VehiclePropConfig& config = result.value();
502     const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
503     if (!isGlobalProp(propId) && areaConfig == nullptr) {
504         // Ignore areaId for global property. For non global property, check whether areaId is
505         // allowed. areaId must appear in areaConfig.
506         return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
507                        << ", not listed in config";
508     }
509     if (auto result = checkPropValue(propValue, &config); !result.ok()) {
510         return Error() << "invalid property value: " << propValue.toString()
511                        << ", error: " << getErrorMsg(result);
512     }
513     if (auto result = checkValueRange(propValue, areaConfig); !result.ok()) {
514         return Error() << "property value out of range: " << propValue.toString()
515                        << ", error: " << getErrorMsg(result);
516     }
517     return {};
518 }
519 
getValues(const CallbackType & callback,const GetValueRequests & requests)520 ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
521                                            const GetValueRequests& requests) {
522     ATRACE_CALL();
523     if (callback == nullptr) {
524         return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
525     }
526     expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
527             deserializedResults = fromStableLargeParcelable(requests);
528     if (!deserializedResults.ok()) {
529         ALOGE("getValues: failed to parse getValues requests");
530         return std::move(deserializedResults.error());
531     }
532     const std::vector<GetValueRequest>& getValueRequests =
533             deserializedResults.value().getObject()->payloads;
534 
535     auto maybeRequestIds = checkDuplicateRequests(getValueRequests);
536     if (!maybeRequestIds.ok()) {
537         ALOGE("getValues: duplicate request ID");
538         return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
539     }
540 
541     // A list of failed result we already know before sending to hardware.
542     std::vector<GetValueResult> failedResults;
543     // The list of requests that we would send to hardware.
544     std::vector<GetValueRequest> hardwareRequests;
545 
546     for (const auto& request : getValueRequests) {
547         if (auto result = checkReadPermission(request.prop); !result.ok()) {
548             ALOGW("property does not support reading: %s", getErrorMsg(result).c_str());
549             failedResults.push_back(GetValueResult{
550                     .requestId = request.requestId,
551                     .status = getErrorCode(result),
552                     .prop = {},
553             });
554             continue;
555         }
556         hardwareRequests.push_back(request);
557     }
558 
559     // The set of request Ids that we would send to hardware.
560     std::unordered_set<int64_t> hardwareRequestIds;
561     for (const auto& request : hardwareRequests) {
562         hardwareRequestIds.insert(request.requestId);
563     }
564 
565     std::shared_ptr<GetValuesClient> client;
566     {
567         // Lock to make sure onBinderDied would not be called concurrently.
568         std::scoped_lock lockGuard(mLock);
569         if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
570             return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
571                                                                "client died");
572         }
573 
574         client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
575     }
576 
577     // Register the pending hardware requests and also check for duplicate request Ids.
578     if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
579         ALOGE("getValues[%s]: failed to add pending requests, error: %s",
580               toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
581         return toScopedAStatus(addRequestResult);
582     }
583 
584     if (!failedResults.empty()) {
585         // First send the failed results we already know back to the client.
586         client->sendResults(std::move(failedResults));
587     }
588 
589     if (hardwareRequests.empty()) {
590         return ScopedAStatus::ok();
591     }
592 
593     if (StatusCode status =
594                 mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests);
595         status != StatusCode::OK) {
596         // If the hardware returns error, finish all the pending requests for this request because
597         // we never expect hardware to call callback for these requests.
598         client->tryFinishRequests(hardwareRequestIds);
599         ALOGE("getValues[%s]: failed to get value from VehicleHardware, status: %d",
600               toString(hardwareRequestIds).c_str(), toInt(status));
601         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
602                 toInt(status), "failed to get value from VehicleHardware");
603     }
604     return ScopedAStatus::ok();
605 }
606 
setValues(const CallbackType & callback,const SetValueRequests & requests)607 ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
608                                            const SetValueRequests& requests) {
609     ATRACE_CALL();
610     if (callback == nullptr) {
611         return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
612     }
613     expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
614             deserializedResults = fromStableLargeParcelable(requests);
615     if (!deserializedResults.ok()) {
616         ALOGE("setValues: failed to parse setValues requests");
617         return std::move(deserializedResults.error());
618     }
619     const std::vector<SetValueRequest>& setValueRequests =
620             deserializedResults.value().getObject()->payloads;
621 
622     // A list of failed result we already know before sending to hardware.
623     std::vector<SetValueResult> failedResults;
624     // The list of requests that we would send to hardware.
625     std::vector<SetValueRequest> hardwareRequests;
626 
627     auto maybeRequestIds = checkDuplicateRequests(setValueRequests);
628     if (!maybeRequestIds.ok()) {
629         ALOGE("setValues: duplicate request ID");
630         return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
631     }
632 
633     for (auto& request : setValueRequests) {
634         int64_t requestId = request.requestId;
635         if (auto result = checkWritePermission(request.value); !result.ok()) {
636             ALOGW("property does not support writing: %s", getErrorMsg(result).c_str());
637             failedResults.push_back(SetValueResult{
638                     .requestId = requestId,
639                     .status = getErrorCode(result),
640             });
641             continue;
642         }
643         if (auto result = checkProperty(request.value); !result.ok()) {
644             ALOGW("setValues[%" PRId64 "]: property is not valid: %s", requestId,
645                   getErrorMsg(result).c_str());
646             failedResults.push_back(SetValueResult{
647                     .requestId = requestId,
648                     .status = StatusCode::INVALID_ARG,
649             });
650             continue;
651         }
652 
653         hardwareRequests.push_back(request);
654     }
655 
656     // The set of request Ids that we would send to hardware.
657     std::unordered_set<int64_t> hardwareRequestIds;
658     for (const auto& request : hardwareRequests) {
659         hardwareRequestIds.insert(request.requestId);
660     }
661 
662     std::shared_ptr<SetValuesClient> client;
663     {
664         // Lock to make sure onBinderDied would not be called concurrently.
665         std::scoped_lock lockGuard(mLock);
666         if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
667             return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
668                                                                "client died");
669         }
670         client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
671     }
672 
673     // Register the pending hardware requests and also check for duplicate request Ids.
674     if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
675         ALOGE("setValues[%s], failed to add pending requests, error: %s",
676               toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
677         return toScopedAStatus(addRequestResult);
678     }
679 
680     if (!failedResults.empty()) {
681         // First send the failed results we already know back to the client.
682         client->sendResults(std::move(failedResults));
683     }
684 
685     if (hardwareRequests.empty()) {
686         return ScopedAStatus::ok();
687     }
688 
689     if (StatusCode status =
690                 mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
691         status != StatusCode::OK) {
692         // If the hardware returns error, finish all the pending requests for this request because
693         // we never expect hardware to call callback for these requests.
694         client->tryFinishRequests(hardwareRequestIds);
695         ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d",
696               toString(hardwareRequestIds).c_str(), toInt(status));
697         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
698                 toInt(status), "failed to set value to VehicleHardware");
699     }
700 
701     return ScopedAStatus::ok();
702 }
703 
704 #define CHECK_DUPLICATE_REQUESTS(PROP_NAME)                                                      \
705     do {                                                                                         \
706         std::vector<int64_t> requestIds;                                                         \
707         std::set<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> requestProps; \
708         for (const auto& request : requests) {                                                   \
709             const auto& prop = request.PROP_NAME;                                                \
710             if (requestProps.count(prop) != 0) {                                                 \
711                 return ::android::base::Error()                                                  \
712                        << "duplicate request for property: " << prop.toString();                 \
713             }                                                                                    \
714             requestProps.insert(prop);                                                           \
715             requestIds.push_back(request.requestId);                                             \
716         }                                                                                        \
717         return requestIds;                                                                       \
718     } while (0);
719 
checkDuplicateRequests(const std::vector<GetValueRequest> & requests)720 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
721         const std::vector<GetValueRequest>& requests) {
722     CHECK_DUPLICATE_REQUESTS(prop);
723 }
724 
checkDuplicateRequests(const std::vector<SetValueRequest> & requests)725 ::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
726         const std::vector<SetValueRequest>& requests) {
727     CHECK_DUPLICATE_REQUESTS(value);
728 }
729 
730 #undef CHECK_DUPLICATE_REQUESTS
731 
getPropConfigs(const std::vector<int32_t> & props,VehiclePropConfigs * output)732 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
733                                                 VehiclePropConfigs* output) {
734     std::vector<VehiclePropConfig> configs;
735 
736     if (!mConfigInit) {
737         for (int32_t prop : props) {
738             auto maybeConfig = mVehicleHardware->getPropertyConfig(prop);
739             if (!maybeConfig.has_value() ||
740                 !isConfigSupportedForCurrentVhalVersion(maybeConfig.value())) {
741                 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
742                         toInt(StatusCode::INVALID_ARG),
743                         StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
744             }
745             configs.push_back(maybeConfig.value());
746         }
747 
748         return vectorToStableLargeParcelable(std::move(configs), output);
749     }
750 
751     ScopedAStatus status = ScopedAStatus::ok();
752     getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
753         SharedScopedLockAssertion lockAssertion(mConfigLock);
754 
755         for (int32_t prop : props) {
756             auto it = configsByPropId.find(prop);
757             if (it != configsByPropId.end()) {
758                 configs.push_back(it->second);
759             } else {
760                 status = ScopedAStatus::fromServiceSpecificErrorWithMessage(
761                         toInt(StatusCode::INVALID_ARG),
762                         StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
763                 return;
764             }
765         }
766     });
767 
768     if (!status.isOk()) {
769         return status;
770     }
771 
772     return vectorToStableLargeParcelable(std::move(configs), output);
773 }
774 
hasRequiredAccess(VehiclePropertyAccess access,VehiclePropertyAccess requiredAccess)775 bool hasRequiredAccess(VehiclePropertyAccess access, VehiclePropertyAccess requiredAccess) {
776     return access == requiredAccess || access == VehiclePropertyAccess::READ_WRITE;
777 }
778 
areaConfigsHaveRequiredAccess(const std::vector<VehicleAreaConfig> & areaConfigs,VehiclePropertyAccess requiredAccess)779 bool areaConfigsHaveRequiredAccess(const std::vector<VehicleAreaConfig>& areaConfigs,
780                                    VehiclePropertyAccess requiredAccess) {
781     if (areaConfigs.empty()) {
782         return false;
783     }
784     for (VehicleAreaConfig areaConfig : areaConfigs) {
785         if (!hasRequiredAccess(areaConfig.access, requiredAccess)) {
786             return false;
787         }
788     }
789     return true;
790 }
791 
checkSubscribeOptions(const std::vector<SubscribeOptions> & options,const std::unordered_map<int32_t,VehiclePropConfig> & configsByPropId)792 VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
793         const std::vector<SubscribeOptions>& options,
794         const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId) {
795     for (const auto& option : options) {
796         int32_t propId = option.propId;
797         auto it = configsByPropId.find(propId);
798         if (it == configsByPropId.end()) {
799             return StatusError(StatusCode::INVALID_ARG)
800                    << StringPrintf("no config for property, ID: %" PRId32, propId);
801         }
802         const VehiclePropConfig& config = it->second;
803         std::vector<VehicleAreaConfig> areaConfigs;
804         if (option.areaIds.empty()) {
805             areaConfigs = config.areaConfigs;
806         } else {
807             std::unordered_map<int, VehicleAreaConfig> areaConfigByAreaId;
808             for (const VehicleAreaConfig& areaConfig : config.areaConfigs) {
809                 areaConfigByAreaId.emplace(areaConfig.areaId, areaConfig);
810             }
811             for (int areaId : option.areaIds) {
812                 auto it = areaConfigByAreaId.find(areaId);
813                 if (it != areaConfigByAreaId.end()) {
814                     areaConfigs.push_back(it->second);
815                 } else if (areaId != 0 || !areaConfigByAreaId.empty()) {
816                     return StatusError(StatusCode::INVALID_ARG)
817                            << StringPrintf("invalid area ID: %" PRId32 " for prop ID: %" PRId32
818                                            ", not listed in config",
819                                            areaId, propId);
820                 }
821             }
822         }
823 
824         if (config.changeMode != VehiclePropertyChangeMode::ON_CHANGE &&
825             config.changeMode != VehiclePropertyChangeMode::CONTINUOUS) {
826             return StatusError(StatusCode::INVALID_ARG)
827                    << "only support subscribing to ON_CHANGE or CONTINUOUS property";
828         }
829 
830         // Either VehiclePropConfig.access or VehicleAreaConfig.access will be specified
831         if (!hasRequiredAccess(config.access, VehiclePropertyAccess::READ) &&
832             !areaConfigsHaveRequiredAccess(areaConfigs, VehiclePropertyAccess::READ)) {
833             return StatusError(StatusCode::ACCESS_DENIED)
834                    << StringPrintf("Property %" PRId32 " has no read access", propId);
835         }
836 
837         if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
838             float sampleRateHz = option.sampleRate;
839             float minSampleRateHz = config.minSampleRate;
840             float maxSampleRateHz = config.maxSampleRate;
841             float defaultRateHz =
842                     getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz);
843             if (sampleRateHz != defaultRateHz) {
844                 ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f "
845                       "HZ",
846                       sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz);
847                 sampleRateHz = defaultRateHz;
848             }
849             if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) {
850                 return StatusError(StatusCode::INVALID_ARG)
851                        << "invalid sample rate: " << sampleRateHz << " HZ";
852             }
853             if (!SubscriptionManager::checkResolution(option.resolution)) {
854                 return StatusError(StatusCode::INVALID_ARG)
855                        << "invalid resolution: " << option.resolution;
856             }
857         }
858     }
859 
860     return {};
861 }
862 
parseSubscribeOptions(const std::vector<SubscribeOptions> & options,const std::unordered_map<int32_t,VehiclePropConfig> & configsByPropId,std::vector<SubscribeOptions> & onChangeSubscriptions,std::vector<SubscribeOptions> & continuousSubscriptions)863 void DefaultVehicleHal::parseSubscribeOptions(
864         const std::vector<SubscribeOptions>& options,
865         const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
866         std::vector<SubscribeOptions>& onChangeSubscriptions,
867         std::vector<SubscribeOptions>& continuousSubscriptions) {
868     for (const auto& option : options) {
869         int32_t propId = option.propId;
870         // We have already validate config exists.
871         const VehiclePropConfig& config = configsByPropId.at(propId);
872 
873         SubscribeOptions optionCopy = option;
874         // If areaIds is empty, subscribe to all areas.
875         if (optionCopy.areaIds.empty() && !isGlobalProp(propId)) {
876             for (const auto& areaConfig : config.areaConfigs) {
877                 optionCopy.areaIds.push_back(areaConfig.areaId);
878             }
879         }
880 
881         if (isGlobalProp(propId)) {
882             optionCopy.areaIds = {0};
883         }
884 
885         if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
886             optionCopy.sampleRate = getDefaultSampleRateHz(
887                     optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate);
888             if (!optionCopy.enableVariableUpdateRate) {
889                 continuousSubscriptions.push_back(std::move(optionCopy));
890             } else {
891                 // If clients enables to VUR, we need to check whether VUR is supported for the
892                 // specific [propId, areaId] and overwrite the option to disable if not supported.
893                 std::vector<int32_t> areasVurEnabled;
894                 std::vector<int32_t> areasVurDisabled;
895                 for (int32_t areaId : optionCopy.areaIds) {
896                     const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
897                     if (areaConfig == nullptr) {
898                         areasVurDisabled.push_back(areaId);
899                         continue;
900                     }
901                     if (!areaConfig->supportVariableUpdateRate) {
902                         areasVurDisabled.push_back(areaId);
903                         continue;
904                     }
905                     areasVurEnabled.push_back(areaId);
906                 }
907                 if (!areasVurEnabled.empty()) {
908                     SubscribeOptions optionVurEnabled = optionCopy;
909                     optionVurEnabled.areaIds = areasVurEnabled;
910                     optionVurEnabled.enableVariableUpdateRate = true;
911                     continuousSubscriptions.push_back(std::move(optionVurEnabled));
912                 }
913 
914                 if (!areasVurDisabled.empty()) {
915                     // We use optionCopy for areas with VUR disabled.
916                     optionCopy.areaIds = areasVurDisabled;
917                     optionCopy.enableVariableUpdateRate = false;
918                     continuousSubscriptions.push_back(std::move(optionCopy));
919                 }
920             }
921         } else {
922             onChangeSubscriptions.push_back(std::move(optionCopy));
923         }
924     }
925 }
926 
subscribe(const CallbackType & callback,const std::vector<SubscribeOptions> & options,int32_t maxSharedMemoryFileCount)927 ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
928                                            const std::vector<SubscribeOptions>& options,
929                                            [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
930     // TODO(b/205189110): Use shared memory file count.
931     if (callback == nullptr) {
932         return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
933     }
934     std::vector<SubscribeOptions> onChangeSubscriptions;
935     std::vector<SubscribeOptions> continuousSubscriptions;
936     ScopedAStatus returnStatus = ScopedAStatus::ok();
937     getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions,
938                         &continuousSubscriptions](const auto& configsByPropId) {
939         SharedScopedLockAssertion lockAssertion(mConfigLock);
940 
941         if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) {
942             ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
943             returnStatus = toScopedAStatus(result);
944             return;
945         }
946         parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions,
947                               continuousSubscriptions);
948     });
949 
950     if (!returnStatus.isOk()) {
951         return returnStatus;
952     }
953 
954     {
955         // Lock to make sure onBinderDied would not be called concurrently
956         // (before subscribe). Without this, we may create a new subscription for an already dead
957         // client which will never be unsubscribed.
958         std::scoped_lock lockGuard(mLock);
959         if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
960             return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
961                                                                "client died");
962         }
963 
964         if (!onChangeSubscriptions.empty()) {
965             auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
966                                                           /*isContinuousProperty=*/false);
967             if (!result.ok()) {
968                 return toScopedAStatus(result);
969             }
970         }
971         if (!continuousSubscriptions.empty()) {
972             auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions,
973                                                           /*isContinuousProperty=*/true);
974             if (!result.ok()) {
975                 return toScopedAStatus(result);
976             }
977         }
978     }
979     return ScopedAStatus::ok();
980 }
981 
unsubscribe(const CallbackType & callback,const std::vector<int32_t> & propIds)982 ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType& callback,
983                                              const std::vector<int32_t>& propIds) {
984     if (callback == nullptr) {
985         return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
986     }
987     return toScopedAStatus(mSubscriptionManager->unsubscribe(callback->asBinder().get(), propIds));
988 }
989 
returnSharedMemory(const CallbackType &,int64_t)990 ScopedAStatus DefaultVehicleHal::returnSharedMemory(const CallbackType&, int64_t) {
991     // TODO(b/200737967): implement this.
992     return ScopedAStatus::ok();
993 }
994 
getAreaConfigForPropIdAreaId(int32_t propId,int32_t areaId) const995 Result<VehicleAreaConfig> DefaultVehicleHal::getAreaConfigForPropIdAreaId(int32_t propId,
996                                                                           int32_t areaId) const {
997     auto result = getConfig(propId);
998     if (!result.ok()) {
999         return Error() << "Failed to get property config for propertyId: " << propIdToString(propId)
1000                        << ", error: " << result.error();
1001     }
1002     const VehiclePropConfig& config = result.value();
1003     const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
1004     if (areaConfig == nullptr) {
1005         return Error() << "AreaId config not found for propertyId: " << propIdToString(propId)
1006                        << ", areaId: " << areaId;
1007     }
1008     return *areaConfig;
1009 }
1010 
getHasSupportedValueInfo(int32_t propId,int32_t areaId) const1011 Result<HasSupportedValueInfo> DefaultVehicleHal::getHasSupportedValueInfo(int32_t propId,
1012                                                                           int32_t areaId) const {
1013     Result<VehicleAreaConfig> propIdAreaIdConfigResult =
1014             getAreaConfigForPropIdAreaId(propId, areaId);
1015     if (!isGlobalProp(propId) && !propIdAreaIdConfigResult.ok()) {
1016         // For global property, it is possible that no config exists.
1017         return Error() << propIdAreaIdConfigResult.error();
1018     }
1019     if (propIdAreaIdConfigResult.has_value()) {
1020         auto areaConfig = propIdAreaIdConfigResult.value();
1021         if (areaConfig.hasSupportedValueInfo.has_value()) {
1022             return areaConfig.hasSupportedValueInfo.value();
1023         }
1024     }
1025     return Error() << "property: " << propIdToString(propId) << ", areaId: " << areaId
1026                    << " does not support this operation because hasSupportedValueInfo is null";
1027 }
1028 
getSupportedValuesLists(const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds,SupportedValuesListResults * supportedValuesListResults)1029 ScopedAStatus DefaultVehicleHal::getSupportedValuesLists(
1030         const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
1031         SupportedValuesListResults* supportedValuesListResults) {
1032     std::vector<size_t> toHardwareRequestCounters;
1033     std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
1034     std::vector<SupportedValuesListResult> results;
1035     results.resize(vhalPropIdAreaIds.size());
1036     for (size_t requestCounter = 0; requestCounter < vhalPropIdAreaIds.size(); requestCounter++) {
1037         const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(requestCounter);
1038         int32_t propId = vhalPropIdAreaId.propId;
1039         int32_t areaId = vhalPropIdAreaId.areaId;
1040         auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
1041         if (!hasSupportedValueInfoResult.ok()) {
1042             ALOGE("getSupportedValuesLists: %s",
1043                   hasSupportedValueInfoResult.error().message().c_str());
1044             results[requestCounter] = SupportedValuesListResult{
1045                     .status = StatusCode::INVALID_ARG, .supportedValuesList = std::nullopt};
1046             continue;
1047         }
1048 
1049         const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
1050         if (hasSupportedValueInfo.hasSupportedValuesList) {
1051             toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
1052             toHardwareRequestCounters.push_back(requestCounter);
1053         } else {
1054             results[requestCounter] = SupportedValuesListResult{
1055                     .status = StatusCode::OK, .supportedValuesList = std::nullopt};
1056             continue;
1057         }
1058     }
1059     if (toHardwarePropIdAreaIds.size() != 0) {
1060         std::vector<SupportedValuesListResult> resultsFromHardware =
1061                 mVehicleHardware->getSupportedValuesLists(toHardwarePropIdAreaIds);
1062         // It is guaranteed that toHardwarePropIdAreaIds, toHardwareRequestCounters,
1063         // resultsFromHardware have the same size.
1064         if (resultsFromHardware.size() != toHardwareRequestCounters.size()) {
1065             return ScopedAStatus::fromServiceSpecificErrorWithMessage(
1066                     toInt(StatusCode::INTERNAL_ERROR),
1067                     fmt::format(
1068                             "getSupportedValuesLists: Unexpected results size from IVehicleHardware"
1069                             ", got: {}, expect: {}",
1070                             resultsFromHardware.size(), toHardwareRequestCounters.size())
1071                             .c_str());
1072         }
1073         for (size_t i = 0; i < toHardwareRequestCounters.size(); i++) {
1074             results[toHardwareRequestCounters[i]] = resultsFromHardware[i];
1075         }
1076     }
1077     ScopedAStatus status =
1078             vectorToStableLargeParcelable(std::move(results), supportedValuesListResults);
1079     if (!status.isOk()) {
1080         int statusCode = status.getServiceSpecificError();
1081         ALOGE("getSupportedValuesLists: failed to marshal result into large parcelable, error: "
1082               "%s, code: %d",
1083               status.getMessage(), statusCode);
1084         return status;
1085     }
1086     return ScopedAStatus::ok();
1087 }
1088 
getMinMaxSupportedValue(const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds,MinMaxSupportedValueResults * minMaxSupportedValueResults)1089 ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(
1090         const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds,
1091         MinMaxSupportedValueResults* minMaxSupportedValueResults) {
1092     std::vector<size_t> toHardwareRequestCounters;
1093     std::vector<PropIdAreaId> toHardwarePropIdAreaIds;
1094     std::vector<MinMaxSupportedValueResult> results;
1095     results.resize(vhalPropIdAreaIds.size());
1096     for (size_t requestCounter = 0; requestCounter < vhalPropIdAreaIds.size(); requestCounter++) {
1097         const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(requestCounter);
1098         int32_t propId = vhalPropIdAreaId.propId;
1099         int32_t areaId = vhalPropIdAreaId.areaId;
1100         auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
1101         if (!hasSupportedValueInfoResult.ok()) {
1102             ALOGE("getMinMaxSupportedValue: %s",
1103                   hasSupportedValueInfoResult.error().message().c_str());
1104             results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::INVALID_ARG,
1105                                                                  .minSupportedValue = std::nullopt,
1106                                                                  .maxSupportedValue = std::nullopt};
1107             continue;
1108         }
1109 
1110         const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
1111         if (hasSupportedValueInfo.hasMinSupportedValue ||
1112             hasSupportedValueInfo.hasMaxSupportedValue) {
1113             toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
1114             toHardwareRequestCounters.push_back(requestCounter);
1115         } else {
1116             results[requestCounter] = MinMaxSupportedValueResult{.status = StatusCode::OK,
1117                                                                  .minSupportedValue = std::nullopt,
1118                                                                  .maxSupportedValue = std::nullopt};
1119             continue;
1120         }
1121     }
1122     if (toHardwarePropIdAreaIds.size() != 0) {
1123         std::vector<MinMaxSupportedValueResult> resultsFromHardware =
1124                 mVehicleHardware->getMinMaxSupportedValues(toHardwarePropIdAreaIds);
1125         // It is guaranteed that toHardwarePropIdAreaIds, toHardwareRequestCounters,
1126         // resultsFromHardware have the same size.
1127         if (resultsFromHardware.size() != toHardwareRequestCounters.size()) {
1128             return ScopedAStatus::fromServiceSpecificErrorWithMessage(
1129                     toInt(StatusCode::INTERNAL_ERROR),
1130                     fmt::format(
1131                             "getMinMaxSupportedValue: Unexpected results size from IVehicleHardware"
1132                             ", got: {}, expect: {}",
1133                             resultsFromHardware.size(), toHardwareRequestCounters.size())
1134                             .c_str());
1135         }
1136         for (size_t i = 0; i < toHardwareRequestCounters.size(); i++) {
1137             results[toHardwareRequestCounters[i]] = resultsFromHardware[i];
1138         }
1139     }
1140     ScopedAStatus status =
1141             vectorToStableLargeParcelable(std::move(results), minMaxSupportedValueResults);
1142     if (!status.isOk()) {
1143         int statusCode = status.getServiceSpecificError();
1144         ALOGE("getMinMaxSupportedValue: failed to marshal result into large parcelable, error: "
1145               "%s, code: %d",
1146               status.getMessage(), statusCode);
1147         return status;
1148     }
1149     return ScopedAStatus::ok();
1150 }
1151 
registerSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback> & callback,const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds)1152 ScopedAStatus DefaultVehicleHal::registerSupportedValueChangeCallback(
1153         const std::shared_ptr<IVehicleCallback>& callback,
1154         const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
1155     std::vector<PropIdAreaId> propIdAreaIdsToSubscribe;
1156     for (size_t i = 0; i < vhalPropIdAreaIds.size(); i++) {
1157         const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(i);
1158         int32_t propId = vhalPropIdAreaId.propId;
1159         int32_t areaId = vhalPropIdAreaId.areaId;
1160         auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
1161         if (!hasSupportedValueInfoResult.ok()) {
1162             ALOGE("registerSupportedValueChangeCallback not supported: %s",
1163                   hasSupportedValueInfoResult.error().message().c_str());
1164             return toScopedAStatus(hasSupportedValueInfoResult, StatusCode::INVALID_ARG);
1165         }
1166         const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
1167         if (!hasSupportedValueInfo.hasMinSupportedValue &&
1168             !hasSupportedValueInfo.hasMaxSupportedValue &&
1169             !hasSupportedValueInfo.hasSupportedValuesList) {
1170             ALOGW("registerSupportedValueChangeCallback: do nothing for property: %s, "
1171                   "areaId: %" PRId32
1172                   ", no min/max supported values or supported values list"
1173                   " specified",
1174                   propIdToString(propId).c_str(), areaId);
1175             continue;
1176         }
1177         propIdAreaIdsToSubscribe.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
1178     }
1179     if (propIdAreaIdsToSubscribe.empty()) {
1180         return ScopedAStatus::ok();
1181     }
1182     {
1183         // Lock to make sure onBinderDied would not be called concurrently
1184         // (before subscribeSupportedValueChange). Without this, we may create a new subscription
1185         // for an already dead client which will never be unsubscribed.
1186         std::scoped_lock lockGuard(mLock);
1187         if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
1188             return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
1189                                                                "client died");
1190         }
1191         auto result = mSubscriptionManager->subscribeSupportedValueChange(callback,
1192                                                                           propIdAreaIdsToSubscribe);
1193         if (!result.ok()) {
1194             ALOGW("registerSupportedValueChangeCallback: failed to subscribe supported value change"
1195                   " for %s, error: %s",
1196                   fmt::format("{}", propIdAreaIdsToSubscribe).c_str(),
1197                   result.error().message().c_str());
1198             return toScopedAStatus(result);
1199         }
1200     }
1201     return ScopedAStatus::ok();
1202 }
1203 
unregisterSupportedValueChangeCallback(const std::shared_ptr<IVehicleCallback> & callback,const std::vector<VhalPropIdAreaId> & vhalPropIdAreaIds)1204 ScopedAStatus DefaultVehicleHal::unregisterSupportedValueChangeCallback(
1205         const std::shared_ptr<IVehicleCallback>& callback,
1206         const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
1207     std::vector<PropIdAreaId> propIdAreaIds;
1208     for (const auto& vhalPropIdAreaId : vhalPropIdAreaIds) {
1209         propIdAreaIds.push_back(
1210                 PropIdAreaId{.propId = vhalPropIdAreaId.propId, .areaId = vhalPropIdAreaId.areaId});
1211     }
1212 
1213     auto result = mSubscriptionManager->unsubscribeSupportedValueChange(callback->asBinder().get(),
1214                                                                         propIdAreaIds);
1215     if (!result.ok()) {
1216         ALOGW("unregisterSupportedValueChangeCallback: failed to unsubscribe supported value change"
1217               " for %s, error: %s",
1218               fmt::format("{}", propIdAreaIds).c_str(), result.error().message().c_str());
1219         return toScopedAStatus(result);
1220     }
1221     return ScopedAStatus::ok();
1222 }
1223 
getHardware()1224 IVehicleHardware* DefaultVehicleHal::getHardware() {
1225     return mVehicleHardware.get();
1226 }
1227 
checkPermissionHelper(const VehiclePropValue & value,VehiclePropertyAccess accessToTest) const1228 VhalResult<void> DefaultVehicleHal::checkPermissionHelper(
1229         const VehiclePropValue& value, VehiclePropertyAccess accessToTest) const {
1230     static const std::unordered_set<VehiclePropertyAccess> validAccesses = {
1231             VehiclePropertyAccess::WRITE, VehiclePropertyAccess::READ,
1232             VehiclePropertyAccess::READ_WRITE};
1233     if (validAccesses.find(accessToTest) == validAccesses.end()) {
1234         return StatusError(StatusCode::INVALID_ARG)
1235                << "checkPermissionHelper parameter is an invalid access type";
1236     }
1237 
1238     int32_t propId = value.prop;
1239     auto result = getConfig(propId);
1240     if (!result.ok()) {
1241         return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
1242     }
1243 
1244     const VehiclePropConfig& config = result.value();
1245     const VehicleAreaConfig* areaConfig = getAreaConfig(value, config);
1246 
1247     if (areaConfig == nullptr && !isGlobalProp(propId)) {
1248         return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId;
1249     }
1250     if (!hasRequiredAccess(config.access, accessToTest) &&
1251         (areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
1252         return StatusError(StatusCode::ACCESS_DENIED)
1253                << StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
1254                                propId, static_cast<int32_t>(accessToTest));
1255     }
1256     return {};
1257 }
1258 
checkWritePermission(const VehiclePropValue & value) const1259 VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
1260     return checkPermissionHelper(value, VehiclePropertyAccess::WRITE);
1261 }
1262 
checkReadPermission(const VehiclePropValue & value) const1263 VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
1264     return checkPermissionHelper(value, VehiclePropertyAccess::READ);
1265 }
1266 
checkHealth(IVehicleHardware * vehicleHardware,std::weak_ptr<SubscriptionManager> subscriptionManager)1267 void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
1268                                     std::weak_ptr<SubscriptionManager> subscriptionManager) {
1269     StatusCode status = vehicleHardware->checkHealth();
1270     if (status != StatusCode::OK) {
1271         ALOGE("VHAL check health returns non-okay status");
1272         return;
1273     }
1274     std::vector<VehiclePropValue> values = {{
1275             .areaId = 0,
1276             .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
1277             .status = VehiclePropertyStatus::AVAILABLE,
1278             .value.int64Values = {uptimeMillis()},
1279     }};
1280     onPropertyChangeEvent(subscriptionManager, std::move(values));
1281     return;
1282 }
1283 
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)1284 binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath(
1285         AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
1286     return AIBinder_linkToDeath(binder, recipient, cookie);
1287 }
1288 
isAlive(const AIBinder * binder)1289 bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) {
1290     return AIBinder_isAlive(binder);
1291 }
1292 
setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> handler)1293 void DefaultVehicleHal::setBinderLifecycleHandler(
1294         std::unique_ptr<BinderLifecycleInterface> handler) {
1295     mBinderLifecycleHandler = std::move(handler);
1296 }
1297 
checkDumpPermission()1298 bool DefaultVehicleHal::checkDumpPermission() {
1299     uid_t uid = AIBinder_getCallingUid();
1300     return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
1301 }
1302 
dump(int fd,const char ** args,uint32_t numArgs)1303 binder_status_t DefaultVehicleHal::dump(int fd, const char** args, uint32_t numArgs) {
1304     if (!checkDumpPermission()) {
1305         dprintf(fd, "Caller must be root, system or shell");
1306         return STATUS_PERMISSION_DENIED;
1307     }
1308 
1309     std::vector<std::string> options;
1310     for (uint32_t i = 0; i < numArgs; i++) {
1311         options.push_back(args[i]);
1312     }
1313     if (options.size() == 1 && options[0] == "-a") {
1314         // Ignore "-a" option. Bugreport will call with this option.
1315         options.clear();
1316     }
1317     DumpResult result = mVehicleHardware->dump(options);
1318     if (result.refreshPropertyConfigs) {
1319         getAllPropConfigsFromHardwareLocked();
1320     }
1321     dprintf(fd, "%s", (result.buffer + "\n").c_str());
1322     if (!result.callerShouldDumpState) {
1323         return STATUS_OK;
1324     }
1325     dprintf(fd, "Vehicle HAL State: \n");
1326     std::unordered_map<int32_t, VehiclePropConfig> configsByPropIdCopy;
1327     getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
1328         SharedScopedLockAssertion lockAssertion(mConfigLock);
1329 
1330         configsByPropIdCopy = configsByPropId;
1331     });
1332     {
1333         std::scoped_lock<std::mutex> lockGuard(mLock);
1334         dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
1335         dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
1336         dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
1337         dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
1338         dprintf(fd, "Currently have %zu subscribe clients\n",
1339                 mSubscriptionManager->countPropertyChangeClients());
1340         dprintf(fd, "Currently have %zu supported values change subscribe clients\n",
1341                 mSubscriptionManager->countSupportedValueChangeClients());
1342     }
1343     return STATUS_OK;
1344 }
1345 
countClients()1346 size_t DefaultVehicleHal::countClients() {
1347     std::scoped_lock<std::mutex> lockGuard(mLock);
1348     return mGetValuesClients.size() + mSetValuesClients.size() +
1349            mSubscriptionManager->countPropertyChangeClients() +
1350            mSubscriptionManager->countSupportedValueChangeClients();
1351 }
1352 
1353 }  // namespace vehicle
1354 }  // namespace automotive
1355 }  // namespace hardware
1356 }  // namespace android
1357