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