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 "HidlVhalClient.h"
18
19 #include "HidlHalPropConfig.h"
20 #include "HidlHalPropValue.h"
21
22 #include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
23 #include <utils/Log.h>
24
25 #include <VehicleUtils.h>
26
27 #include <memory>
28 #include <vector>
29
30 namespace android {
31 namespace frameworks {
32 namespace automotive {
33 namespace vhal {
34
35 namespace {
36
37 using ::android::sp;
38 using ::android::wp;
39 using ::android::hardware::hidl_vec;
40 using ::android::hardware::Return;
41 using ::android::hardware::automotive::vehicle::toInt;
42 using ::android::hardware::automotive::vehicle::V2_0::IVehicle;
43 using ::android::hardware::automotive::vehicle::V2_0::StatusCode;
44 using ::android::hardware::automotive::vehicle::V2_0::SubscribeFlags;
45 using ::android::hardware::automotive::vehicle::V2_0::SubscribeOptions;
46 using ::android::hardware::automotive::vehicle::V2_0::VehiclePropConfig;
47 using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValue;
48 using ::android::hidl::base::V1_0::IBase;
49
toAidlStatusCode(StatusCode code)50 aidl::android::hardware::automotive::vehicle::StatusCode toAidlStatusCode(StatusCode code) {
51 return static_cast<aidl::android::hardware::automotive::vehicle::StatusCode>(code);
52 }
53
54 } // namespace
55
create()56 std::shared_ptr<IVhalClient> HidlVhalClient::create() {
57 sp<IVehicle> hidlVhal = IVehicle::getService();
58 if (hidlVhal == nullptr) {
59 ALOGD("HIDL VHAL service is not declared or not available");
60 return nullptr;
61 }
62 return std::make_shared<HidlVhalClient>(hidlVhal);
63 }
64
tryCreate()65 std::shared_ptr<IVhalClient> HidlVhalClient::tryCreate() {
66 sp<IVehicle> hidlVhal = IVehicle::tryGetService();
67 if (hidlVhal == nullptr) {
68 return nullptr;
69 }
70 return std::make_shared<HidlVhalClient>(hidlVhal);
71 }
72
tryCreate(const char * descriptor)73 std::shared_ptr<IVhalClient> HidlVhalClient::tryCreate(const char* descriptor) {
74 sp<IVehicle> hidlVhal = IVehicle::tryGetService(descriptor);
75 if (hidlVhal == nullptr) {
76 return nullptr;
77 }
78 return std::make_shared<HidlVhalClient>(hidlVhal);
79 }
80
HidlVhalClient(sp<IVehicle> hal)81 HidlVhalClient::HidlVhalClient(sp<IVehicle> hal) : mHal(hal) {
82 mDeathRecipient = sp<HidlVhalClient::DeathRecipient>::make(this);
83 mHal->linkToDeath(mDeathRecipient, /*cookie=*/0);
84 }
85
~HidlVhalClient()86 HidlVhalClient::~HidlVhalClient() {
87 mHal->unlinkToDeath(mDeathRecipient);
88 }
89
isAidlVhal()90 bool HidlVhalClient::isAidlVhal() {
91 return false;
92 }
93
createHalPropValue(int32_t propId)94 std::unique_ptr<IHalPropValue> HidlVhalClient::createHalPropValue(int32_t propId) {
95 return std::make_unique<HidlHalPropValue>(propId);
96 }
97
createHalPropValue(int32_t propId,int32_t areaId)98 std::unique_ptr<IHalPropValue> HidlVhalClient::createHalPropValue(int32_t propId, int32_t areaId) {
99 return std::make_unique<HidlHalPropValue>(propId, areaId);
100 }
101
getValue(const IHalPropValue & requestValue,std::shared_ptr<GetValueCallbackFunc> callback)102 void HidlVhalClient::getValue(const IHalPropValue& requestValue,
103 std::shared_ptr<GetValueCallbackFunc> callback) {
104 const VehiclePropValue* propValue =
105 reinterpret_cast<const VehiclePropValue*>(requestValue.toVehiclePropValue());
106 int32_t propId = requestValue.getPropId();
107 int32_t areaId = requestValue.getAreaId();
108 auto result =
109 mHal->get(*propValue,
110 [callback, propId, areaId](StatusCode status, const VehiclePropValue& value) {
111 if (status == StatusCode::OK) {
112 VehiclePropValue valueCopy = value;
113 (*callback)(std::make_unique<HidlHalPropValue>(std::move(valueCopy)));
114 } else {
115 (*callback)(ClientStatusError(toAidlStatusCode(status))
116 << "failed to get value for prop: " << propId
117 << ", areaId: " << areaId
118 << ": status code: " << toInt(status));
119 }
120 });
121
122 if (!result.isOk()) {
123 (*callback)(ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
124 << "failed to get value for prop: " << requestValue.getPropId() << ", areaId: "
125 << requestValue.getAreaId() << ": error: " << result.description());
126 }
127 }
128
setValue(const IHalPropValue & value,std::shared_ptr<HidlVhalClient::SetValueCallbackFunc> callback)129 void HidlVhalClient::setValue(const IHalPropValue& value,
130 std::shared_ptr<HidlVhalClient::SetValueCallbackFunc> callback) {
131 const VehiclePropValue* propValue =
132 reinterpret_cast<const VehiclePropValue*>(value.toVehiclePropValue());
133 auto result = mHal->set(*propValue);
134 if (!result.isOk()) {
135 (*callback)(ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
136 << "failed to set value for prop: " << value.getPropId()
137 << ", areaId: " << value.getAreaId() << ": error: " << result.description());
138 return;
139 }
140 StatusCode status = result;
141 if (status != StatusCode::OK) {
142 (*callback)(ClientStatusError(toAidlStatusCode(status))
143 << "failed to set value for prop: " << value.getPropId()
144 << ", areaId: " << value.getAreaId() << ": status code: " << toInt(status));
145 return;
146 }
147 (*callback)({});
148 }
149
150 // Add the callback that would be called when VHAL binder died.
addOnBinderDiedCallback(std::shared_ptr<OnBinderDiedCallbackFunc> callback)151 VhalClientResult<void> HidlVhalClient::addOnBinderDiedCallback(
152 std::shared_ptr<OnBinderDiedCallbackFunc> callback) {
153 std::lock_guard<std::mutex> lk(mLock);
154 mOnBinderDiedCallbacks.insert(callback);
155 return {};
156 }
157
158 // Remove a previously added OnBinderDied callback.
removeOnBinderDiedCallback(std::shared_ptr<OnBinderDiedCallbackFunc> callback)159 VhalClientResult<void> HidlVhalClient::removeOnBinderDiedCallback(
160 std::shared_ptr<OnBinderDiedCallbackFunc> callback) {
161 std::lock_guard<std::mutex> lk(mLock);
162 if (mOnBinderDiedCallbacks.find(callback) == mOnBinderDiedCallbacks.end()) {
163 return ClientStatusError(toAidlStatusCode(StatusCode::INVALID_ARG))
164 << "The callback to remove was not added before";
165 }
166 mOnBinderDiedCallbacks.erase(callback);
167 return {};
168 }
169
getAllPropConfigs()170 VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> HidlVhalClient::getAllPropConfigs() {
171 std::vector<std::unique_ptr<IHalPropConfig>> halPropConfigs;
172 auto result = mHal->getAllPropConfigs([&halPropConfigs](
173 const hidl_vec<VehiclePropConfig>& propConfigs) {
174 for (const VehiclePropConfig& config : propConfigs) {
175 VehiclePropConfig configCopy = config;
176 halPropConfigs.push_back(std::make_unique<HidlHalPropConfig>(std::move(configCopy)));
177 }
178 });
179 if (!result.isOk()) {
180 return ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
181 << "failed to getAllPropConfigs: error: " << result.description();
182 }
183 return std::move(halPropConfigs);
184 }
185
getPropConfigs(std::vector<int32_t> propIds)186 VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> HidlVhalClient::getPropConfigs(
187 std::vector<int32_t> propIds) {
188 std::vector<std::unique_ptr<IHalPropConfig>> halPropConfigs;
189 hidl_vec<int32_t> hidlPropIds(propIds);
190 StatusCode status;
191 auto result =
192 mHal->getPropConfigs(hidlPropIds,
193 [&status,
194 &halPropConfigs](StatusCode s,
195 const hidl_vec<VehiclePropConfig>& propConfigs) {
196 status = s;
197 if (s != StatusCode::OK) {
198 return;
199 }
200 for (const VehiclePropConfig& config : propConfigs) {
201 VehiclePropConfig configCopy = config;
202 halPropConfigs.push_back(
203 std::make_unique<HidlHalPropConfig>(
204 std::move(configCopy)));
205 }
206 });
207 if (!result.isOk()) {
208 return ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
209 << "failed to getPropConfigs: error: " << result.description();
210 }
211 if (status != StatusCode::OK) {
212 return ClientStatusError(toAidlStatusCode(status))
213 << "failed to getPropConfigs: status code: " << toInt(status);
214 }
215 return std::move(halPropConfigs);
216 }
217
getSubscriptionClient(std::shared_ptr<ISubscriptionCallback> callback)218 std::unique_ptr<ISubscriptionClient> HidlVhalClient::getSubscriptionClient(
219 std::shared_ptr<ISubscriptionCallback> callback) {
220 return std::make_unique<HidlSubscriptionClient>(mHal, callback);
221 }
222
onBinderDied()223 void HidlVhalClient::onBinderDied() {
224 std::unordered_set<std::shared_ptr<OnBinderDiedCallbackFunc>> callbacksCopy;
225 {
226 // Copy the callbacks so that we avoid invoking the callback with lock hold.
227 std::lock_guard<std::mutex> lk(mLock);
228 callbacksCopy = mOnBinderDiedCallbacks;
229 }
230 for (auto callback : callbacksCopy) {
231 (*callback)();
232 }
233 }
234
DeathRecipient(HidlVhalClient * client)235 HidlVhalClient::DeathRecipient::DeathRecipient(HidlVhalClient* client) : mClient(client) {}
236
serviceDied(uint64_t cookie,const wp<IBase> & who)237 void HidlVhalClient::DeathRecipient::serviceDied([[maybe_unused]] uint64_t cookie,
238 [[maybe_unused]] const wp<IBase>& who) {
239 mClient->onBinderDied();
240 }
241
HidlSubscriptionClient(sp<IVehicle> hal,std::shared_ptr<ISubscriptionCallback> callback)242 HidlSubscriptionClient::HidlSubscriptionClient(sp<IVehicle> hal,
243 std::shared_ptr<ISubscriptionCallback> callback) :
244 mCallback(callback), mHal(hal) {
245 mVhalCallback = sp<SubscriptionCallback>::make(callback);
246 }
247
subscribe(const std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions> & options)248 VhalClientResult<void> HidlSubscriptionClient::subscribe(
249 const std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
250 options) {
251 std::vector<SubscribeOptions> hidlOptions;
252 for (const auto& option : options) {
253 hidlOptions.push_back(SubscribeOptions{
254 .propId = option.propId,
255 .sampleRate = option.sampleRate,
256 .flags = SubscribeFlags::EVENTS_FROM_CAR,
257 });
258 }
259 auto result = mHal->subscribe(mVhalCallback, hidlOptions);
260 if (!result.isOk()) {
261 return ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
262 << "failed to subscribe: error: " << result.description();
263 }
264 StatusCode status = result;
265 if (status != StatusCode::OK) {
266 return ClientStatusError(toAidlStatusCode(status))
267 << "failed to subscribe: status code: " << toInt(status);
268 }
269 return {};
270 }
271
unsubscribe(const std::vector<int32_t> & propIds)272 VhalClientResult<void> HidlSubscriptionClient::unsubscribe(const std::vector<int32_t>& propIds) {
273 for (int32_t propId : propIds) {
274 auto result = mHal->unsubscribe(mVhalCallback, propId);
275 if (!result.isOk()) {
276 return ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
277 << "failed to unsubscribe prop Id: " << propId
278 << ": error: " << result.description();
279 }
280 StatusCode status = result;
281 if (status != StatusCode::OK) {
282 return ClientStatusError(toAidlStatusCode(status))
283 << "failed to unsubscribe prop Id: " << propId
284 << ": status code: " << toInt(status);
285 }
286 }
287 return {};
288 }
289
SubscriptionCallback(std::shared_ptr<ISubscriptionCallback> callback)290 SubscriptionCallback::SubscriptionCallback(std::shared_ptr<ISubscriptionCallback> callback) :
291 mCallback(callback) {}
292
onPropertyEvent(const hidl_vec<VehiclePropValue> & propValues)293 Return<void> SubscriptionCallback::onPropertyEvent(const hidl_vec<VehiclePropValue>& propValues) {
294 std::vector<std::unique_ptr<IHalPropValue>> halPropValues;
295 for (const VehiclePropValue& value : propValues) {
296 VehiclePropValue valueCopy = value;
297 halPropValues.push_back(std::make_unique<HidlHalPropValue>(std::move(valueCopy)));
298 }
299 mCallback->onPropertyEvent(halPropValues);
300 return {};
301 }
302
onPropertySet(const VehiclePropValue & propValue)303 Return<void> SubscriptionCallback::onPropertySet(
304 [[maybe_unused]] const VehiclePropValue& propValue) {
305 // Deprecated
306 return {};
307 }
308
onPropertySetError(StatusCode status,int32_t propId,int32_t areaId)309 Return<void> SubscriptionCallback::onPropertySetError(StatusCode status, int32_t propId,
310 int32_t areaId) {
311 std::vector<HalPropError> halPropErrors;
312 halPropErrors.push_back(HalPropError{
313 .propId = propId,
314 .areaId = areaId,
315 .status =
316 static_cast<::aidl::android::hardware::automotive::vehicle::StatusCode>(status),
317 });
318 mCallback->onPropertySetError(halPropErrors);
319 return {};
320 }
321
322 } // namespace vhal
323 } // namespace automotive
324 } // namespace frameworks
325 } // namespace android
326