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