• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::lock_guard<std::mutex> lk(mLock);
225     for (auto callback : mOnBinderDiedCallbacks) {
226         (*callback)();
227     }
228 }
229 
DeathRecipient(HidlVhalClient * client)230 HidlVhalClient::DeathRecipient::DeathRecipient(HidlVhalClient* client) : mClient(client) {}
231 
serviceDied(uint64_t cookie,const wp<IBase> & who)232 void HidlVhalClient::DeathRecipient::serviceDied([[maybe_unused]] uint64_t cookie,
233                                                  [[maybe_unused]] const wp<IBase>& who) {
234     mClient->onBinderDied();
235 }
236 
HidlSubscriptionClient(sp<IVehicle> hal,std::shared_ptr<ISubscriptionCallback> callback)237 HidlSubscriptionClient::HidlSubscriptionClient(sp<IVehicle> hal,
238                                                std::shared_ptr<ISubscriptionCallback> callback) :
239       mCallback(callback), mHal(hal) {
240     mVhalCallback = sp<SubscriptionCallback>::make(callback);
241 }
242 
subscribe(const std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions> & options)243 VhalClientResult<void> HidlSubscriptionClient::subscribe(
244         const std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
245                 options) {
246     std::vector<SubscribeOptions> hidlOptions;
247     for (const auto& option : options) {
248         hidlOptions.push_back(SubscribeOptions{
249                 .propId = option.propId,
250                 .sampleRate = option.sampleRate,
251                 .flags = SubscribeFlags::EVENTS_FROM_CAR,
252         });
253     }
254     auto result = mHal->subscribe(mVhalCallback, hidlOptions);
255     if (!result.isOk()) {
256         return ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
257                 << "failed to subscribe: error: " << result.description();
258     }
259     StatusCode status = result;
260     if (status != StatusCode::OK) {
261         return ClientStatusError(toAidlStatusCode(status))
262                 << "failed to subscribe: status code: " << toInt(status);
263     }
264     return {};
265 }
266 
unsubscribe(const std::vector<int32_t> & propIds)267 VhalClientResult<void> HidlSubscriptionClient::unsubscribe(const std::vector<int32_t>& propIds) {
268     for (int32_t propId : propIds) {
269         auto result = mHal->unsubscribe(mVhalCallback, propId);
270         if (!result.isOk()) {
271             return ClientStatusError(toAidlStatusCode(StatusCode::TRY_AGAIN))
272                     << "failed to unsubscribe prop Id: " << propId
273                     << ": error: " << result.description();
274         }
275         StatusCode status = result;
276         if (status != StatusCode::OK) {
277             return ClientStatusError(toAidlStatusCode(status))
278                     << "failed to unsubscribe prop Id: " << propId
279                     << ": status code: " << toInt(status);
280         }
281     }
282     return {};
283 }
284 
SubscriptionCallback(std::shared_ptr<ISubscriptionCallback> callback)285 SubscriptionCallback::SubscriptionCallback(std::shared_ptr<ISubscriptionCallback> callback) :
286       mCallback(callback) {}
287 
onPropertyEvent(const hidl_vec<VehiclePropValue> & propValues)288 Return<void> SubscriptionCallback::onPropertyEvent(const hidl_vec<VehiclePropValue>& propValues) {
289     std::vector<std::unique_ptr<IHalPropValue>> halPropValues;
290     for (const VehiclePropValue& value : propValues) {
291         VehiclePropValue valueCopy = value;
292         halPropValues.push_back(std::make_unique<HidlHalPropValue>(std::move(valueCopy)));
293     }
294     mCallback->onPropertyEvent(halPropValues);
295     return {};
296 }
297 
onPropertySet(const VehiclePropValue & propValue)298 Return<void> SubscriptionCallback::onPropertySet(
299         [[maybe_unused]] const VehiclePropValue& propValue) {
300     // Deprecated
301     return {};
302 }
303 
onPropertySetError(StatusCode status,int32_t propId,int32_t areaId)304 Return<void> SubscriptionCallback::onPropertySetError(StatusCode status, int32_t propId,
305                                                       int32_t areaId) {
306     std::vector<HalPropError> halPropErrors;
307     halPropErrors.push_back(HalPropError{
308             .propId = propId,
309             .areaId = areaId,
310             .status =
311                     static_cast<::aidl::android::hardware::automotive::vehicle::StatusCode>(status),
312     });
313     mCallback->onPropertySetError(halPropErrors);
314     return {};
315 }
316 
317 }  // namespace vhal
318 }  // namespace automotive
319 }  // namespace frameworks
320 }  // namespace android
321