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