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