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