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