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