• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022, 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 #include "AidlVhalClient.h"
18 
19 #include <android-base/stringprintf.h>
20 #include <android-base/strings.h>
21 #include <android/binder_manager.h>
22 #include <android/binder_process.h>
23 #include <utils/Log.h>
24 
25 #include <AidlHalPropConfig.h>
26 #include <AidlHalPropValue.h>
27 #include <ParcelableUtils.h>
28 #include <inttypes.h>
29 
30 #include <string>
31 #include <vector>
32 
33 namespace android {
34 namespace frameworks {
35 namespace automotive {
36 namespace vhal {
37 
38 namespace {
39 
40 using ::android::base::Join;
41 using ::android::base::StringPrintf;
42 using ::android::hardware::automotive::vehicle::fromStableLargeParcelable;
43 using ::android::hardware::automotive::vehicle::PendingRequestPool;
44 using ::android::hardware::automotive::vehicle::toInt;
45 using ::android::hardware::automotive::vehicle::vectorToStableLargeParcelable;
46 
47 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
48 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
49 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
50 using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
51 using ::aidl::android::hardware::automotive::vehicle::IVehicle;
52 using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
53 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
54 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
55 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
56 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
57 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
58 using ::aidl::android::hardware::automotive::vehicle::toString;
59 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
60 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
61 using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
62 using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
63 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
64 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
65 
66 using ::ndk::ScopedAIBinder_DeathRecipient;
67 using ::ndk::ScopedAStatus;
68 using ::ndk::SharedRefBase;
69 using ::ndk::SpAIBinder;
70 
toString(const std::vector<int32_t> & values)71 std::string toString(const std::vector<int32_t>& values) {
72     std::vector<std::string> strings;
73     for (int32_t value : values) {
74         strings.push_back(std::to_string(value));
75     }
76     return "[" + Join(strings, ",") + "]";
77 }
78 
79 }  // namespace
80 
create()81 std::shared_ptr<IVhalClient> AidlVhalClient::create() {
82     if (!AServiceManager_isDeclared(AIDL_VHAL_SERVICE)) {
83         ALOGD("AIDL VHAL service is not declared, maybe HIDL VHAL is used instead?");
84         return nullptr;
85     }
86     std::shared_ptr<IVehicle> aidlVhal =
87             IVehicle::fromBinder(SpAIBinder(AServiceManager_waitForService(AIDL_VHAL_SERVICE)));
88     if (aidlVhal == nullptr) {
89         ALOGW("AIDL VHAL service is not available");
90         return nullptr;
91     }
92     ABinderProcess_startThreadPool();
93     return std::make_shared<AidlVhalClient>(aidlVhal);
94 }
95 
tryCreate()96 std::shared_ptr<IVhalClient> AidlVhalClient::tryCreate() {
97     return tryCreate(AIDL_VHAL_SERVICE);
98 }
99 
tryCreate(const char * descriptor)100 std::shared_ptr<IVhalClient> AidlVhalClient::tryCreate(const char* descriptor) {
101     if (!AServiceManager_isDeclared(descriptor)) {
102         ALOGD("AIDL VHAL service, descriptor: %s is not declared, maybe HIDL VHAL is used instead?",
103               descriptor);
104         return nullptr;
105     }
106     std::shared_ptr<IVehicle> aidlVhal =
107             IVehicle::fromBinder(SpAIBinder(AServiceManager_getService(descriptor)));
108     if (aidlVhal == nullptr) {
109         ALOGW("AIDL VHAL service, descriptor: %s is not available", descriptor);
110         return nullptr;
111     }
112     ABinderProcess_startThreadPool();
113     return std::make_shared<AidlVhalClient>(aidlVhal);
114 }
115 
AidlVhalClient(std::shared_ptr<IVehicle> hal)116 AidlVhalClient::AidlVhalClient(std::shared_ptr<IVehicle> hal) :
117       AidlVhalClient(hal, DEFAULT_TIMEOUT_IN_SEC * 1'000) {}
118 
AidlVhalClient(std::shared_ptr<IVehicle> hal,int64_t timeoutInMs)119 AidlVhalClient::AidlVhalClient(std::shared_ptr<IVehicle> hal, int64_t timeoutInMs) :
120       AidlVhalClient(hal, timeoutInMs, std::make_unique<DefaultLinkUnlinkImpl>()) {}
121 
AidlVhalClient(std::shared_ptr<IVehicle> hal,int64_t timeoutInMs,std::unique_ptr<ILinkUnlinkToDeath> linkUnlinkImpl)122 AidlVhalClient::AidlVhalClient(std::shared_ptr<IVehicle> hal, int64_t timeoutInMs,
123                                std::unique_ptr<ILinkUnlinkToDeath> linkUnlinkImpl) :
124       mHal(hal) {
125     mGetSetValueClient = SharedRefBase::make<GetSetValueClient>(
126             /*timeoutInNs=*/timeoutInMs * 1'000'000, hal);
127     mDeathRecipient = ScopedAIBinder_DeathRecipient(
128             AIBinder_DeathRecipient_new(&AidlVhalClient::onBinderDied));
129     mLinkUnlinkImpl = std::move(linkUnlinkImpl);
130     binder_status_t status =
131             mLinkUnlinkImpl->linkToDeath(hal->asBinder().get(), mDeathRecipient.get(),
132                                          static_cast<void*>(this));
133     if (status != STATUS_OK) {
134         ALOGE("failed to link to VHAL death, status: %d", static_cast<int32_t>(status));
135     }
136 }
137 
~AidlVhalClient()138 AidlVhalClient::~AidlVhalClient() {
139     mLinkUnlinkImpl->unlinkToDeath(mHal->asBinder().get(), mDeathRecipient.get(),
140                                    static_cast<void*>(this));
141 }
142 
isAidlVhal()143 bool AidlVhalClient::isAidlVhal() {
144     return true;
145 }
146 
createHalPropValue(int32_t propId)147 std::unique_ptr<IHalPropValue> AidlVhalClient::createHalPropValue(int32_t propId) {
148     return std::make_unique<AidlHalPropValue>(propId);
149 }
150 
createHalPropValue(int32_t propId,int32_t areaId)151 std::unique_ptr<IHalPropValue> AidlVhalClient::createHalPropValue(int32_t propId, int32_t areaId) {
152     return std::make_unique<AidlHalPropValue>(propId, areaId);
153 }
154 
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)155 binder_status_t AidlVhalClient::DefaultLinkUnlinkImpl::linkToDeath(
156         AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
157     return AIBinder_linkToDeath(binder, recipient, cookie);
158 }
159 
unlinkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)160 binder_status_t AidlVhalClient::DefaultLinkUnlinkImpl::unlinkToDeath(
161         AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
162     return AIBinder_unlinkToDeath(binder, recipient, cookie);
163 }
164 
getValue(const IHalPropValue & requestValue,std::shared_ptr<GetValueCallbackFunc> callback)165 void AidlVhalClient::getValue(const IHalPropValue& requestValue,
166                               std::shared_ptr<GetValueCallbackFunc> callback) {
167     int64_t requestId = mRequestId++;
168     mGetSetValueClient->getValue(requestId, requestValue, callback, mGetSetValueClient);
169 }
170 
setValue(const IHalPropValue & requestValue,std::shared_ptr<SetValueCallbackFunc> callback)171 void AidlVhalClient::setValue(const IHalPropValue& requestValue,
172                               std::shared_ptr<SetValueCallbackFunc> callback) {
173     int64_t requestId = mRequestId++;
174     mGetSetValueClient->setValue(requestId, requestValue, callback, mGetSetValueClient);
175 }
176 
addOnBinderDiedCallback(std::shared_ptr<OnBinderDiedCallbackFunc> callback)177 VhalClientResult<void> AidlVhalClient::addOnBinderDiedCallback(
178         std::shared_ptr<OnBinderDiedCallbackFunc> callback) {
179     std::lock_guard<std::mutex> lk(mLock);
180     mOnBinderDiedCallbacks.insert(callback);
181     return {};
182 }
183 
removeOnBinderDiedCallback(std::shared_ptr<OnBinderDiedCallbackFunc> callback)184 VhalClientResult<void> AidlVhalClient::removeOnBinderDiedCallback(
185         std::shared_ptr<OnBinderDiedCallbackFunc> callback) {
186     std::lock_guard<std::mutex> lk(mLock);
187     if (mOnBinderDiedCallbacks.find(callback) == mOnBinderDiedCallbacks.end()) {
188         return ClientStatusError(ErrorCode::INVALID_ARG)
189                 << "The callback to remove was not added before";
190     }
191     mOnBinderDiedCallbacks.erase(callback);
192     return {};
193 }
194 
getAllPropConfigs()195 VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> AidlVhalClient::getAllPropConfigs() {
196     VehiclePropConfigs configs;
197     if (ScopedAStatus status = mHal->getAllPropConfigs(&configs); !status.isOk()) {
198         return statusToError<
199                 std::vector<std::unique_ptr<IHalPropConfig>>>(status,
200                                                               "failed to get all property configs");
201     }
202     return parseVehiclePropConfigs(configs);
203 }
204 
getPropConfigs(std::vector<int32_t> propIds)205 VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> AidlVhalClient::getPropConfigs(
206         std::vector<int32_t> propIds) {
207     VehiclePropConfigs configs;
208     if (ScopedAStatus status = mHal->getPropConfigs(propIds, &configs); !status.isOk()) {
209         return statusToError<std::vector<std::unique_ptr<
210                 IHalPropConfig>>>(status,
211                                   StringPrintf("failed to get prop configs for prop IDs: %s",
212                                                toString(propIds).c_str()));
213     }
214     return parseVehiclePropConfigs(configs);
215 }
216 
217 VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>>
parseVehiclePropConfigs(const VehiclePropConfigs & configs)218 AidlVhalClient::parseVehiclePropConfigs(const VehiclePropConfigs& configs) {
219     auto parcelableResult = fromStableLargeParcelable(configs);
220     if (!parcelableResult.ok()) {
221         return ClientStatusError(ErrorCode::INTERNAL_ERROR_FROM_VHAL)
222                 << "failed to parse VehiclePropConfigs returned from VHAL, error: "
223                 << parcelableResult.error().getMessage();
224     }
225     std::vector<std::unique_ptr<IHalPropConfig>> out;
226     for (const VehiclePropConfig& config : parcelableResult.value().getObject()->payloads) {
227         VehiclePropConfig configCopy = config;
228         out.push_back(std::make_unique<AidlHalPropConfig>(std::move(configCopy)));
229     }
230     return out;
231 }
232 
onBinderDied(void * cookie)233 void AidlVhalClient::onBinderDied(void* cookie) {
234     AidlVhalClient* vhalClient = reinterpret_cast<AidlVhalClient*>(cookie);
235     vhalClient->onBinderDiedWithContext();
236 }
237 
onBinderUnlinked(void * cookie)238 void AidlVhalClient::onBinderUnlinked(void* cookie) {
239     AidlVhalClient* vhalClient = reinterpret_cast<AidlVhalClient*>(cookie);
240     vhalClient->onBinderUnlinkedWithContext();
241 }
242 
onBinderDiedWithContext()243 void AidlVhalClient::onBinderDiedWithContext() {
244     std::lock_guard<std::mutex> lk(mLock);
245     for (auto callback : mOnBinderDiedCallbacks) {
246         (*callback)();
247     }
248 }
249 
onBinderUnlinkedWithContext()250 void AidlVhalClient::onBinderUnlinkedWithContext() {
251     std::lock_guard<std::mutex> lk(mLock);
252     mOnBinderDiedCallbacks.clear();
253 }
254 
countOnBinderDiedCallbacks()255 size_t AidlVhalClient::countOnBinderDiedCallbacks() {
256     std::lock_guard<std::mutex> lk(mLock);
257     return mOnBinderDiedCallbacks.size();
258 }
259 
getSubscriptionClient(std::shared_ptr<ISubscriptionCallback> callback)260 std::unique_ptr<ISubscriptionClient> AidlVhalClient::getSubscriptionClient(
261         std::shared_ptr<ISubscriptionCallback> callback) {
262     return std::make_unique<AidlSubscriptionClient>(mHal, callback);
263 }
264 
GetSetValueClient(int64_t timeoutInNs,std::shared_ptr<IVehicle> hal)265 GetSetValueClient::GetSetValueClient(int64_t timeoutInNs, std::shared_ptr<IVehicle> hal) :
266       mHal(hal) {
267     mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNs);
268     mOnGetValueTimeout = std::make_unique<PendingRequestPool::TimeoutCallbackFunc>(
269             [this](const std::unordered_set<int64_t>& requestIds) {
270                 onTimeout(requestIds, &mPendingGetValueCallbacks);
271             });
272     mOnSetValueTimeout = std::make_unique<PendingRequestPool::TimeoutCallbackFunc>(
273             [this](const std::unordered_set<int64_t>& requestIds) {
274                 onTimeout(requestIds, &mPendingSetValueCallbacks);
275             });
276 }
277 
~GetSetValueClient()278 GetSetValueClient::~GetSetValueClient() {
279     // Delete the pending request pool, mark all pending request as timed-out.
280     mPendingRequestPool.reset();
281 }
282 
getValue(int64_t requestId,const IHalPropValue & requestValue,std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> clientCallback,std::shared_ptr<GetSetValueClient> vhalCallback)283 void GetSetValueClient::getValue(
284         int64_t requestId, const IHalPropValue& requestValue,
285         std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> clientCallback,
286         std::shared_ptr<GetSetValueClient> vhalCallback) {
287     int32_t propId = requestValue.getPropId();
288     int32_t areaId = requestValue.getAreaId();
289     std::vector<GetValueRequest> requests = {
290             {
291                     .requestId = requestId,
292                     .prop = *(reinterpret_cast<const VehiclePropValue*>(
293                             requestValue.toVehiclePropValue())),
294             },
295     };
296 
297     GetValueRequests getValueRequests;
298     ScopedAStatus status = vectorToStableLargeParcelable(std::move(requests), &getValueRequests);
299     if (!status.isOk()) {
300         tryFinishGetValueRequest(requestId);
301         (*clientCallback)(AidlVhalClient::statusToError<
302                           std::unique_ptr<IHalPropValue>>(status,
303                                                           StringPrintf("failed to serialize "
304                                                                        "request for prop: %" PRId32
305                                                                        ", areaId: %" PRId32,
306                                                                        propId, areaId)));
307     }
308 
309     addGetValueRequest(requestId, requestValue, clientCallback);
310     status = mHal->getValues(vhalCallback, getValueRequests);
311     if (!status.isOk()) {
312         tryFinishGetValueRequest(requestId);
313         (*clientCallback)(
314                 AidlVhalClient::statusToError<std::unique_ptr<
315                         IHalPropValue>>(status,
316                                         StringPrintf("failed to get value for prop: %" PRId32
317                                                      ", areaId: %" PRId32,
318                                                      propId, areaId)));
319     }
320 }
321 
setValue(int64_t requestId,const IHalPropValue & requestValue,std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> clientCallback,std::shared_ptr<GetSetValueClient> vhalCallback)322 void GetSetValueClient::setValue(
323         int64_t requestId, const IHalPropValue& requestValue,
324         std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> clientCallback,
325         std::shared_ptr<GetSetValueClient> vhalCallback) {
326     int32_t propId = requestValue.getPropId();
327     int32_t areaId = requestValue.getAreaId();
328     std::vector<SetValueRequest> requests = {
329             {
330                     .requestId = requestId,
331                     .value = *(reinterpret_cast<const VehiclePropValue*>(
332                             requestValue.toVehiclePropValue())),
333             },
334     };
335 
336     SetValueRequests setValueRequests;
337     ScopedAStatus status = vectorToStableLargeParcelable(std::move(requests), &setValueRequests);
338     if (!status.isOk()) {
339         tryFinishSetValueRequest(requestId);
340         (*clientCallback)(AidlVhalClient::statusToError<
341                           void>(status,
342                                 StringPrintf("failed to serialize request for prop: %" PRId32
343                                              ", areaId: %" PRId32,
344                                              propId, areaId)));
345     }
346 
347     addSetValueRequest(requestId, requestValue, clientCallback);
348     status = mHal->setValues(vhalCallback, setValueRequests);
349     if (!status.isOk()) {
350         tryFinishSetValueRequest(requestId);
351         (*clientCallback)(AidlVhalClient::statusToError<
352                           void>(status,
353                                 StringPrintf("failed to set value for prop: %" PRId32
354                                              ", areaId: %" PRId32,
355                                              propId, areaId)));
356     }
357 }
358 
addGetValueRequest(int64_t requestId,const IHalPropValue & requestProp,std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback)359 void GetSetValueClient::addGetValueRequest(
360         int64_t requestId, const IHalPropValue& requestProp,
361         std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback) {
362     std::lock_guard<std::mutex> lk(mLock);
363     mPendingGetValueCallbacks[requestId] =
364             std::make_unique<PendingGetValueRequest>(PendingGetValueRequest{
365                     .callback = callback,
366                     .propId = requestProp.getPropId(),
367                     .areaId = requestProp.getAreaId(),
368             });
369     mPendingRequestPool->addRequests(/*clientId=*/nullptr, {requestId}, mOnGetValueTimeout);
370 }
371 
addSetValueRequest(int64_t requestId,const IHalPropValue & requestProp,std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback)372 void GetSetValueClient::addSetValueRequest(
373         int64_t requestId, const IHalPropValue& requestProp,
374         std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback) {
375     std::lock_guard<std::mutex> lk(mLock);
376     mPendingSetValueCallbacks[requestId] =
377             std::make_unique<PendingSetValueRequest>(PendingSetValueRequest{
378                     .callback = callback,
379                     .propId = requestProp.getPropId(),
380                     .areaId = requestProp.getAreaId(),
381             });
382     mPendingRequestPool->addRequests(/*clientId=*/nullptr, {requestId}, mOnSetValueTimeout);
383 }
384 
385 std::unique_ptr<GetSetValueClient::PendingGetValueRequest>
tryFinishGetValueRequest(int64_t requestId)386 GetSetValueClient::tryFinishGetValueRequest(int64_t requestId) {
387     std::lock_guard<std::mutex> lk(mLock);
388     return tryFinishRequest(requestId, &mPendingGetValueCallbacks);
389 }
390 
391 std::unique_ptr<GetSetValueClient::PendingSetValueRequest>
tryFinishSetValueRequest(int64_t requestId)392 GetSetValueClient::tryFinishSetValueRequest(int64_t requestId) {
393     std::lock_guard<std::mutex> lk(mLock);
394     return tryFinishRequest(requestId, &mPendingSetValueCallbacks);
395 }
396 
397 template <class T>
tryFinishRequest(int64_t requestId,std::unordered_map<int64_t,std::unique_ptr<T>> * callbacks)398 std::unique_ptr<T> GetSetValueClient::tryFinishRequest(
399         int64_t requestId, std::unordered_map<int64_t, std::unique_ptr<T>>* callbacks) {
400     auto finished = mPendingRequestPool->tryFinishRequests(/*clientId=*/nullptr, {requestId});
401     if (finished.empty()) {
402         return nullptr;
403     }
404     auto it = callbacks->find(requestId);
405     if (it == callbacks->end()) {
406         return nullptr;
407     }
408     auto request = std::move(it->second);
409     callbacks->erase(requestId);
410     return std::move(request);
411 }
412 
413 template std::unique_ptr<GetSetValueClient::PendingGetValueRequest>
414 GetSetValueClient::tryFinishRequest(
415         int64_t requestId,
416         std::unordered_map<int64_t, std::unique_ptr<PendingGetValueRequest>>* callbacks);
417 template std::unique_ptr<GetSetValueClient::PendingSetValueRequest>
418 GetSetValueClient::tryFinishRequest(
419         int64_t requestId,
420         std::unordered_map<int64_t, std::unique_ptr<PendingSetValueRequest>>* callbacks);
421 
onGetValues(const GetValueResults & results)422 ScopedAStatus GetSetValueClient::onGetValues(const GetValueResults& results) {
423     auto parcelableResult = fromStableLargeParcelable(results);
424     if (!parcelableResult.ok()) {
425         ALOGE("failed to parse GetValueResults returned from VHAL, error: %s",
426               parcelableResult.error().getMessage());
427         return std::move(parcelableResult.error());
428     }
429     for (const GetValueResult& result : parcelableResult.value().getObject()->payloads) {
430         onGetValue(result);
431     }
432     return ScopedAStatus::ok();
433 }
434 
onGetValue(const GetValueResult & result)435 void GetSetValueClient::onGetValue(const GetValueResult& result) {
436     int64_t requestId = result.requestId;
437 
438     auto pendingRequest = tryFinishGetValueRequest(requestId);
439     if (pendingRequest == nullptr) {
440         ALOGD("failed to find pending request for ID: %" PRId64 ", maybe already timed-out",
441               requestId);
442         return;
443     }
444 
445     std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback = pendingRequest->callback;
446     int32_t propId = pendingRequest->propId;
447     int32_t areaId = pendingRequest->areaId;
448     if (result.status != StatusCode::OK) {
449         StatusCode status = result.status;
450         (*callback)(ClientStatusError(status)
451                     << "failed to get value for propId: " << propId << ", areaId: " << areaId
452                     << ": status: " << toString(status));
453     } else if (!result.prop.has_value()) {
454         (*callback)(ClientStatusError(ErrorCode::INTERNAL_ERROR_FROM_VHAL)
455                     << "failed to get value for propId: " << propId << ", areaId: " << areaId
456                     << ": returns no value");
457     } else {
458         VehiclePropValue valueCopy = result.prop.value();
459         std::unique_ptr<IHalPropValue> propValue =
460                 std::make_unique<AidlHalPropValue>(std::move(valueCopy));
461         (*callback)(std::move(propValue));
462     }
463 }
464 
onSetValues(const SetValueResults & results)465 ScopedAStatus GetSetValueClient::onSetValues(const SetValueResults& results) {
466     auto parcelableResult = fromStableLargeParcelable(results);
467     if (!parcelableResult.ok()) {
468         ALOGE("failed to parse SetValueResults returned from VHAL, error: %s",
469               parcelableResult.error().getMessage());
470         return std::move(parcelableResult.error());
471     }
472     for (const SetValueResult& result : parcelableResult.value().getObject()->payloads) {
473         onSetValue(result);
474     }
475     return ScopedAStatus::ok();
476 }
477 
onSetValue(const SetValueResult & result)478 void GetSetValueClient::onSetValue(const SetValueResult& result) {
479     int64_t requestId = result.requestId;
480 
481     auto pendingRequest = tryFinishSetValueRequest(requestId);
482     if (pendingRequest == nullptr) {
483         ALOGD("failed to find pending request for ID: %" PRId64 ", maybe already timed-out",
484               requestId);
485         return;
486     }
487 
488     std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback = pendingRequest->callback;
489     int32_t propId = pendingRequest->propId;
490     int32_t areaId = pendingRequest->areaId;
491     if (result.status != StatusCode::OK) {
492         (*callback)(ClientStatusError(result.status)
493                     << "failed to set value for propId: " << propId << ", areaId: " << areaId
494                     << ": status: " << toString(result.status));
495     } else {
496         (*callback)({});
497     }
498 }
499 
onPropertyEvent(const VehiclePropValues &,int32_t)500 ScopedAStatus GetSetValueClient::onPropertyEvent([[maybe_unused]] const VehiclePropValues&,
501                                                  int32_t) {
502     return ScopedAStatus::
503             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
504                                                 "onPropertyEvent should never be "
505                                                 "called from GetSetValueClient");
506 }
507 
onPropertySetError(const VehiclePropErrors &)508 ScopedAStatus GetSetValueClient::onPropertySetError([[maybe_unused]] const VehiclePropErrors&) {
509     return ScopedAStatus::
510             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
511                                                 "onPropertySetError should never be "
512                                                 "called from GetSetValueClient");
513 }
514 
515 template <class T>
onTimeout(const std::unordered_set<int64_t> & requestIds,std::unordered_map<int64_t,std::unique_ptr<T>> * callbacks)516 void GetSetValueClient::onTimeout(const std::unordered_set<int64_t>& requestIds,
517                                   std::unordered_map<int64_t, std::unique_ptr<T>>* callbacks) {
518     for (int64_t requestId : requestIds) {
519         std::unique_ptr<T> pendingRequest;
520         {
521             std::lock_guard<std::mutex> lk(mLock);
522             auto it = callbacks->find(requestId);
523             if (it == callbacks->end()) {
524                 ALOGW("failed to find the timed-out pending request for ID: %" PRId64 ", ignore",
525                       requestId);
526                 continue;
527             }
528             pendingRequest = std::move(it->second);
529             callbacks->erase(requestId);
530         }
531 
532         (*pendingRequest->callback)(
533                 ClientStatusError(ErrorCode::TIMEOUT)
534                 << "failed to get/set value for propId: " << pendingRequest->propId
535                 << ", areaId: " << pendingRequest->areaId << ": request timed out");
536     }
537 }
538 
539 template void GetSetValueClient::onTimeout(
540         const std::unordered_set<int64_t>& requestIds,
541         std::unordered_map<int64_t, std::unique_ptr<PendingGetValueRequest>>* callbacks);
542 template void GetSetValueClient::onTimeout(
543         const std::unordered_set<int64_t>& requestIds,
544         std::unordered_map<int64_t, std::unique_ptr<PendingSetValueRequest>>* callbacks);
545 
AidlSubscriptionClient(std::shared_ptr<IVehicle> hal,std::shared_ptr<ISubscriptionCallback> callback)546 AidlSubscriptionClient::AidlSubscriptionClient(std::shared_ptr<IVehicle> hal,
547                                                std::shared_ptr<ISubscriptionCallback> callback) :
548       mHal(hal) {
549     mSubscriptionCallback = SharedRefBase::make<SubscriptionVehicleCallback>(callback);
550 }
551 
subscribe(const std::vector<SubscribeOptions> & options)552 VhalClientResult<void> AidlSubscriptionClient::subscribe(
553         const std::vector<SubscribeOptions>& options) {
554     std::vector<int32_t> propIds;
555     for (const SubscribeOptions& option : options) {
556         propIds.push_back(option.propId);
557     }
558 
559     // TODO(b/205189110): Fill in maxSharedMemoryFileCount after we support memory pool.
560     if (auto status = mHal->subscribe(mSubscriptionCallback, options,
561                                       /*maxSharedMemoryFileCount=*/0);
562         !status.isOk()) {
563         return AidlVhalClient::statusToError<
564                 void>(status,
565                       StringPrintf("failed to subscribe to prop IDs: %s",
566                                    toString(propIds).c_str()));
567     }
568     return {};
569 }
570 
unsubscribe(const std::vector<int32_t> & propIds)571 VhalClientResult<void> AidlSubscriptionClient::unsubscribe(const std::vector<int32_t>& propIds) {
572     if (auto status = mHal->unsubscribe(mSubscriptionCallback, propIds); !status.isOk()) {
573         return AidlVhalClient::statusToError<
574                 void>(status,
575                       StringPrintf("failed to unsubscribe to prop IDs: %s",
576                                    toString(propIds).c_str()));
577     }
578     return {};
579 }
580 
SubscriptionVehicleCallback(std::shared_ptr<ISubscriptionCallback> callback)581 SubscriptionVehicleCallback::SubscriptionVehicleCallback(
582         std::shared_ptr<ISubscriptionCallback> callback) :
583       mCallback(callback) {}
584 
onGetValues(const GetValueResults & results)585 ScopedAStatus SubscriptionVehicleCallback::onGetValues(
586         [[maybe_unused]] const GetValueResults& results) {
587     return ScopedAStatus::
588             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
589                                                 "onGetValues should never be called "
590                                                 "from SubscriptionVehicleCallback");
591 }
592 
onSetValues(const SetValueResults & results)593 ScopedAStatus SubscriptionVehicleCallback::onSetValues(
594         [[maybe_unused]] const SetValueResults& results) {
595     return ScopedAStatus::
596             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
597                                                 "onSetValues should never be called "
598                                                 "from SubscriptionVehicleCallback");
599 }
600 
onPropertyEvent(const VehiclePropValues & values,int32_t sharedMemoryCount)601 ScopedAStatus SubscriptionVehicleCallback::onPropertyEvent(
602         const VehiclePropValues& values, [[maybe_unused]] int32_t sharedMemoryCount) {
603     auto parcelableResult = fromStableLargeParcelable(values);
604     if (!parcelableResult.ok()) {
605         return ScopedAStatus::
606                 fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
607                                                     StringPrintf("failed to parse "
608                                                                  "VehiclePropValues returned from "
609                                                                  "VHAL, error: %s",
610                                                                  parcelableResult.error()
611                                                                          .getMessage())
612                                                             .c_str());
613     }
614 
615     std::vector<std::unique_ptr<IHalPropValue>> halPropValues;
616     for (const VehiclePropValue& value : parcelableResult.value().getObject()->payloads) {
617         VehiclePropValue valueCopy = value;
618         halPropValues.push_back(std::make_unique<AidlHalPropValue>(std::move(valueCopy)));
619     }
620     mCallback->onPropertyEvent(halPropValues);
621     return ScopedAStatus::ok();
622 }
623 
onPropertySetError(const VehiclePropErrors & errors)624 ScopedAStatus SubscriptionVehicleCallback::onPropertySetError(const VehiclePropErrors& errors) {
625     auto parcelableResult = fromStableLargeParcelable(errors);
626     if (!parcelableResult.ok()) {
627         return ScopedAStatus::
628                 fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
629                                                     StringPrintf("failed to parse "
630                                                                  "VehiclePropErrors returned from "
631                                                                  "VHAL, error: %s",
632                                                                  parcelableResult.error()
633                                                                          .getMessage())
634                                                             .c_str());
635     }
636     std::vector<HalPropError> halPropErrors;
637     for (const VehiclePropError& error : parcelableResult.value().getObject()->payloads) {
638         halPropErrors.push_back(HalPropError{
639                 .propId = error.propId,
640                 .areaId = error.areaId,
641                 .status = error.errorCode,
642         });
643     }
644     mCallback->onPropertySetError(halPropErrors);
645     return ScopedAStatus::ok();
646 }
647 
648 }  // namespace vhal
649 }  // namespace automotive
650 }  // namespace frameworks
651 }  // namespace android
652