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 
getRemoteInterfaceVersion()260 int32_t AidlVhalClient::getRemoteInterfaceVersion() {
261     int32_t interfaceVersion = 0;
262     if (auto status = mHal->getInterfaceVersion(&interfaceVersion); !status.isOk()) {
263         ALOGE("failed to get VHAL interface version, assume 0");
264     }
265     return interfaceVersion;
266 }
267 
getSubscriptionClient(std::shared_ptr<ISubscriptionCallback> callback)268 std::unique_ptr<ISubscriptionClient> AidlVhalClient::getSubscriptionClient(
269         std::shared_ptr<ISubscriptionCallback> callback) {
270     return std::make_unique<AidlSubscriptionClient>(mHal, callback);
271 }
272 
GetSetValueClient(int64_t timeoutInNs,std::shared_ptr<IVehicle> hal)273 GetSetValueClient::GetSetValueClient(int64_t timeoutInNs, std::shared_ptr<IVehicle> hal) :
274       mHal(hal) {
275     mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNs);
276     mOnGetValueTimeout = std::make_unique<PendingRequestPool::TimeoutCallbackFunc>(
277             [this](const std::unordered_set<int64_t>& requestIds) {
278                 onTimeout(requestIds, &mPendingGetValueCallbacks);
279             });
280     mOnSetValueTimeout = std::make_unique<PendingRequestPool::TimeoutCallbackFunc>(
281             [this](const std::unordered_set<int64_t>& requestIds) {
282                 onTimeout(requestIds, &mPendingSetValueCallbacks);
283             });
284 }
285 
~GetSetValueClient()286 GetSetValueClient::~GetSetValueClient() {
287     // Delete the pending request pool, mark all pending request as timed-out.
288     mPendingRequestPool.reset();
289 }
290 
getValue(int64_t requestId,const IHalPropValue & requestValue,std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> clientCallback,std::shared_ptr<GetSetValueClient> vhalCallback)291 void GetSetValueClient::getValue(
292         int64_t requestId, const IHalPropValue& requestValue,
293         std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> clientCallback,
294         std::shared_ptr<GetSetValueClient> vhalCallback) {
295     int32_t propId = requestValue.getPropId();
296     int32_t areaId = requestValue.getAreaId();
297     std::vector<GetValueRequest> requests = {
298             {
299                     .requestId = requestId,
300                     .prop = *(reinterpret_cast<const VehiclePropValue*>(
301                             requestValue.toVehiclePropValue())),
302             },
303     };
304 
305     GetValueRequests getValueRequests;
306     ScopedAStatus status = vectorToStableLargeParcelable(std::move(requests), &getValueRequests);
307     if (!status.isOk()) {
308         tryFinishGetValueRequest(requestId);
309         (*clientCallback)(AidlVhalClient::statusToError<
310                           std::unique_ptr<IHalPropValue>>(status,
311                                                           StringPrintf("failed to serialize "
312                                                                        "request for prop: %" PRId32
313                                                                        ", areaId: %" PRId32,
314                                                                        propId, areaId)));
315     }
316 
317     addGetValueRequest(requestId, requestValue, clientCallback);
318     status = mHal->getValues(vhalCallback, getValueRequests);
319     if (!status.isOk()) {
320         tryFinishGetValueRequest(requestId);
321         (*clientCallback)(
322                 AidlVhalClient::statusToError<std::unique_ptr<
323                         IHalPropValue>>(status,
324                                         StringPrintf("failed to get value for prop: %" PRId32
325                                                      ", areaId: %" PRId32,
326                                                      propId, areaId)));
327     }
328 }
329 
setValue(int64_t requestId,const IHalPropValue & requestValue,std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> clientCallback,std::shared_ptr<GetSetValueClient> vhalCallback)330 void GetSetValueClient::setValue(
331         int64_t requestId, const IHalPropValue& requestValue,
332         std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> clientCallback,
333         std::shared_ptr<GetSetValueClient> vhalCallback) {
334     int32_t propId = requestValue.getPropId();
335     int32_t areaId = requestValue.getAreaId();
336     std::vector<SetValueRequest> requests = {
337             {
338                     .requestId = requestId,
339                     .value = *(reinterpret_cast<const VehiclePropValue*>(
340                             requestValue.toVehiclePropValue())),
341             },
342     };
343 
344     SetValueRequests setValueRequests;
345     ScopedAStatus status = vectorToStableLargeParcelable(std::move(requests), &setValueRequests);
346     if (!status.isOk()) {
347         tryFinishSetValueRequest(requestId);
348         (*clientCallback)(AidlVhalClient::statusToError<
349                           void>(status,
350                                 StringPrintf("failed to serialize request for prop: %" PRId32
351                                              ", areaId: %" PRId32,
352                                              propId, areaId)));
353     }
354 
355     addSetValueRequest(requestId, requestValue, clientCallback);
356     status = mHal->setValues(vhalCallback, setValueRequests);
357     if (!status.isOk()) {
358         tryFinishSetValueRequest(requestId);
359         (*clientCallback)(AidlVhalClient::statusToError<
360                           void>(status,
361                                 StringPrintf("failed to set value for prop: %" PRId32
362                                              ", areaId: %" PRId32,
363                                              propId, areaId)));
364     }
365 }
366 
addGetValueRequest(int64_t requestId,const IHalPropValue & requestProp,std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback)367 void GetSetValueClient::addGetValueRequest(
368         int64_t requestId, const IHalPropValue& requestProp,
369         std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback) {
370     std::lock_guard<std::mutex> lk(mLock);
371     mPendingGetValueCallbacks[requestId] =
372             std::make_unique<PendingGetValueRequest>(PendingGetValueRequest{
373                     .callback = callback,
374                     .propId = requestProp.getPropId(),
375                     .areaId = requestProp.getAreaId(),
376             });
377     mPendingRequestPool->addRequests(/*clientId=*/nullptr, {requestId}, mOnGetValueTimeout);
378 }
379 
addSetValueRequest(int64_t requestId,const IHalPropValue & requestProp,std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback)380 void GetSetValueClient::addSetValueRequest(
381         int64_t requestId, const IHalPropValue& requestProp,
382         std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback) {
383     std::lock_guard<std::mutex> lk(mLock);
384     mPendingSetValueCallbacks[requestId] =
385             std::make_unique<PendingSetValueRequest>(PendingSetValueRequest{
386                     .callback = callback,
387                     .propId = requestProp.getPropId(),
388                     .areaId = requestProp.getAreaId(),
389             });
390     mPendingRequestPool->addRequests(/*clientId=*/nullptr, {requestId}, mOnSetValueTimeout);
391 }
392 
393 std::unique_ptr<GetSetValueClient::PendingGetValueRequest>
tryFinishGetValueRequest(int64_t requestId)394 GetSetValueClient::tryFinishGetValueRequest(int64_t requestId) {
395     std::lock_guard<std::mutex> lk(mLock);
396     return tryFinishRequest(requestId, &mPendingGetValueCallbacks);
397 }
398 
399 std::unique_ptr<GetSetValueClient::PendingSetValueRequest>
tryFinishSetValueRequest(int64_t requestId)400 GetSetValueClient::tryFinishSetValueRequest(int64_t requestId) {
401     std::lock_guard<std::mutex> lk(mLock);
402     return tryFinishRequest(requestId, &mPendingSetValueCallbacks);
403 }
404 
405 template <class T>
tryFinishRequest(int64_t requestId,std::unordered_map<int64_t,std::unique_ptr<T>> * callbacks)406 std::unique_ptr<T> GetSetValueClient::tryFinishRequest(
407         int64_t requestId, std::unordered_map<int64_t, std::unique_ptr<T>>* callbacks) {
408     auto finished = mPendingRequestPool->tryFinishRequests(/*clientId=*/nullptr, {requestId});
409     if (finished.empty()) {
410         return nullptr;
411     }
412     auto it = callbacks->find(requestId);
413     if (it == callbacks->end()) {
414         return nullptr;
415     }
416     auto request = std::move(it->second);
417     callbacks->erase(requestId);
418     return std::move(request);
419 }
420 
421 template std::unique_ptr<GetSetValueClient::PendingGetValueRequest>
422 GetSetValueClient::tryFinishRequest(
423         int64_t requestId,
424         std::unordered_map<int64_t, std::unique_ptr<PendingGetValueRequest>>* callbacks);
425 template std::unique_ptr<GetSetValueClient::PendingSetValueRequest>
426 GetSetValueClient::tryFinishRequest(
427         int64_t requestId,
428         std::unordered_map<int64_t, std::unique_ptr<PendingSetValueRequest>>* callbacks);
429 
onGetValues(const GetValueResults & results)430 ScopedAStatus GetSetValueClient::onGetValues(const GetValueResults& results) {
431     auto parcelableResult = fromStableLargeParcelable(results);
432     if (!parcelableResult.ok()) {
433         ALOGE("failed to parse GetValueResults returned from VHAL, error: %s",
434               parcelableResult.error().getMessage());
435         return std::move(parcelableResult.error());
436     }
437     for (const GetValueResult& result : parcelableResult.value().getObject()->payloads) {
438         onGetValue(result);
439     }
440     return ScopedAStatus::ok();
441 }
442 
onGetValue(const GetValueResult & result)443 void GetSetValueClient::onGetValue(const GetValueResult& result) {
444     int64_t requestId = result.requestId;
445 
446     auto pendingRequest = tryFinishGetValueRequest(requestId);
447     if (pendingRequest == nullptr) {
448         ALOGD("failed to find pending request for ID: %" PRId64 ", maybe already timed-out",
449               requestId);
450         return;
451     }
452 
453     std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback = pendingRequest->callback;
454     int32_t propId = pendingRequest->propId;
455     int32_t areaId = pendingRequest->areaId;
456     if (result.status != StatusCode::OK) {
457         StatusCode status = result.status;
458         (*callback)(ClientStatusError(status)
459                     << "failed to get value for propId: " << propId << ", areaId: " << areaId
460                     << ": status: " << toString(status));
461     } else if (!result.prop.has_value()) {
462         (*callback)(ClientStatusError(ErrorCode::INTERNAL_ERROR_FROM_VHAL)
463                     << "failed to get value for propId: " << propId << ", areaId: " << areaId
464                     << ": returns no value");
465     } else {
466         VehiclePropValue valueCopy = result.prop.value();
467         std::unique_ptr<IHalPropValue> propValue =
468                 std::make_unique<AidlHalPropValue>(std::move(valueCopy));
469         (*callback)(std::move(propValue));
470     }
471 }
472 
onSetValues(const SetValueResults & results)473 ScopedAStatus GetSetValueClient::onSetValues(const SetValueResults& results) {
474     auto parcelableResult = fromStableLargeParcelable(results);
475     if (!parcelableResult.ok()) {
476         ALOGE("failed to parse SetValueResults returned from VHAL, error: %s",
477               parcelableResult.error().getMessage());
478         return std::move(parcelableResult.error());
479     }
480     for (const SetValueResult& result : parcelableResult.value().getObject()->payloads) {
481         onSetValue(result);
482     }
483     return ScopedAStatus::ok();
484 }
485 
onSetValue(const SetValueResult & result)486 void GetSetValueClient::onSetValue(const SetValueResult& result) {
487     int64_t requestId = result.requestId;
488 
489     auto pendingRequest = tryFinishSetValueRequest(requestId);
490     if (pendingRequest == nullptr) {
491         ALOGD("failed to find pending request for ID: %" PRId64 ", maybe already timed-out",
492               requestId);
493         return;
494     }
495 
496     std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback = pendingRequest->callback;
497     int32_t propId = pendingRequest->propId;
498     int32_t areaId = pendingRequest->areaId;
499     if (result.status != StatusCode::OK) {
500         (*callback)(ClientStatusError(result.status)
501                     << "failed to set value for propId: " << propId << ", areaId: " << areaId
502                     << ": status: " << toString(result.status));
503     } else {
504         (*callback)({});
505     }
506 }
507 
onPropertyEvent(const VehiclePropValues &,int32_t)508 ScopedAStatus GetSetValueClient::onPropertyEvent([[maybe_unused]] const VehiclePropValues&,
509                                                  int32_t) {
510     return ScopedAStatus::
511             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
512                                                 "onPropertyEvent should never be "
513                                                 "called from GetSetValueClient");
514 }
515 
onPropertySetError(const VehiclePropErrors &)516 ScopedAStatus GetSetValueClient::onPropertySetError([[maybe_unused]] const VehiclePropErrors&) {
517     return ScopedAStatus::
518             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
519                                                 "onPropertySetError should never be "
520                                                 "called from GetSetValueClient");
521 }
522 
523 template <class T>
onTimeout(const std::unordered_set<int64_t> & requestIds,std::unordered_map<int64_t,std::unique_ptr<T>> * callbacks)524 void GetSetValueClient::onTimeout(const std::unordered_set<int64_t>& requestIds,
525                                   std::unordered_map<int64_t, std::unique_ptr<T>>* callbacks) {
526     for (int64_t requestId : requestIds) {
527         std::unique_ptr<T> pendingRequest;
528         {
529             std::lock_guard<std::mutex> lk(mLock);
530             auto it = callbacks->find(requestId);
531             if (it == callbacks->end()) {
532                 ALOGW("failed to find the timed-out pending request for ID: %" PRId64 ", ignore",
533                       requestId);
534                 continue;
535             }
536             pendingRequest = std::move(it->second);
537             callbacks->erase(requestId);
538         }
539 
540         (*pendingRequest->callback)(
541                 ClientStatusError(ErrorCode::TIMEOUT)
542                 << "failed to get/set value for propId: " << pendingRequest->propId
543                 << ", areaId: " << pendingRequest->areaId << ": request timed out");
544     }
545 }
546 
547 template void GetSetValueClient::onTimeout(
548         const std::unordered_set<int64_t>& requestIds,
549         std::unordered_map<int64_t, std::unique_ptr<PendingGetValueRequest>>* callbacks);
550 template void GetSetValueClient::onTimeout(
551         const std::unordered_set<int64_t>& requestIds,
552         std::unordered_map<int64_t, std::unique_ptr<PendingSetValueRequest>>* callbacks);
553 
AidlSubscriptionClient(std::shared_ptr<IVehicle> hal,std::shared_ptr<ISubscriptionCallback> callback)554 AidlSubscriptionClient::AidlSubscriptionClient(std::shared_ptr<IVehicle> hal,
555                                                std::shared_ptr<ISubscriptionCallback> callback) :
556       mHal(hal) {
557     mSubscriptionCallback = SharedRefBase::make<SubscriptionVehicleCallback>(callback);
558 }
559 
subscribe(const std::vector<SubscribeOptions> & options)560 VhalClientResult<void> AidlSubscriptionClient::subscribe(
561         const std::vector<SubscribeOptions>& options) {
562     std::vector<int32_t> propIds;
563     for (const SubscribeOptions& option : options) {
564         propIds.push_back(option.propId);
565     }
566 
567     // TODO(b/205189110): Fill in maxSharedMemoryFileCount after we support memory pool.
568     if (auto status = mHal->subscribe(mSubscriptionCallback, options,
569                                       /*maxSharedMemoryFileCount=*/0);
570         !status.isOk()) {
571         return AidlVhalClient::statusToError<
572                 void>(status,
573                       StringPrintf("failed to subscribe to prop IDs: %s",
574                                    toString(propIds).c_str()));
575     }
576     return {};
577 }
578 
unsubscribe(const std::vector<int32_t> & propIds)579 VhalClientResult<void> AidlSubscriptionClient::unsubscribe(const std::vector<int32_t>& propIds) {
580     if (auto status = mHal->unsubscribe(mSubscriptionCallback, propIds); !status.isOk()) {
581         return AidlVhalClient::statusToError<
582                 void>(status,
583                       StringPrintf("failed to unsubscribe to prop IDs: %s",
584                                    toString(propIds).c_str()));
585     }
586     return {};
587 }
588 
SubscriptionVehicleCallback(std::shared_ptr<ISubscriptionCallback> callback)589 SubscriptionVehicleCallback::SubscriptionVehicleCallback(
590         std::shared_ptr<ISubscriptionCallback> callback) :
591       mCallback(callback) {}
592 
onGetValues(const GetValueResults & results)593 ScopedAStatus SubscriptionVehicleCallback::onGetValues(
594         [[maybe_unused]] const GetValueResults& results) {
595     return ScopedAStatus::
596             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
597                                                 "onGetValues should never be called "
598                                                 "from SubscriptionVehicleCallback");
599 }
600 
onSetValues(const SetValueResults & results)601 ScopedAStatus SubscriptionVehicleCallback::onSetValues(
602         [[maybe_unused]] const SetValueResults& results) {
603     return ScopedAStatus::
604             fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
605                                                 "onSetValues should never be called "
606                                                 "from SubscriptionVehicleCallback");
607 }
608 
onPropertyEvent(const VehiclePropValues & values,int32_t sharedMemoryCount)609 ScopedAStatus SubscriptionVehicleCallback::onPropertyEvent(
610         const VehiclePropValues& values, [[maybe_unused]] int32_t sharedMemoryCount) {
611     auto parcelableResult = fromStableLargeParcelable(values);
612     if (!parcelableResult.ok()) {
613         return ScopedAStatus::
614                 fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
615                                                     StringPrintf("failed to parse "
616                                                                  "VehiclePropValues returned from "
617                                                                  "VHAL, error: %s",
618                                                                  parcelableResult.error()
619                                                                          .getMessage())
620                                                             .c_str());
621     }
622 
623     std::vector<std::unique_ptr<IHalPropValue>> halPropValues;
624     for (const VehiclePropValue& value : parcelableResult.value().getObject()->payloads) {
625         VehiclePropValue valueCopy = value;
626         halPropValues.push_back(std::make_unique<AidlHalPropValue>(std::move(valueCopy)));
627     }
628     mCallback->onPropertyEvent(halPropValues);
629     return ScopedAStatus::ok();
630 }
631 
onPropertySetError(const VehiclePropErrors & errors)632 ScopedAStatus SubscriptionVehicleCallback::onPropertySetError(const VehiclePropErrors& errors) {
633     auto parcelableResult = fromStableLargeParcelable(errors);
634     if (!parcelableResult.ok()) {
635         return ScopedAStatus::
636                 fromServiceSpecificErrorWithMessage(toInt(ErrorCode::INTERNAL_ERROR_FROM_VHAL),
637                                                     StringPrintf("failed to parse "
638                                                                  "VehiclePropErrors returned from "
639                                                                  "VHAL, error: %s",
640                                                                  parcelableResult.error()
641                                                                          .getMessage())
642                                                             .c_str());
643     }
644     std::vector<HalPropError> halPropErrors;
645     for (const VehiclePropError& error : parcelableResult.value().getObject()->payloads) {
646         halPropErrors.push_back(HalPropError{
647                 .propId = error.propId,
648                 .areaId = error.areaId,
649                 .status = error.errorCode,
650         });
651     }
652     mCallback->onPropertySetError(halPropErrors);
653     return ScopedAStatus::ok();
654 }
655 
656 }  // namespace vhal
657 }  // namespace automotive
658 }  // namespace frameworks
659 }  // namespace android
660