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