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