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 #ifndef CPP_VHAL_CLIENT_INCLUDE_AIDLVHALCLIENT_H_
18 #define CPP_VHAL_CLIENT_INCLUDE_AIDLVHALCLIENT_H_
19 
20 #include "IVhalClient.h"
21 
22 #include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
23 #include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
24 #include <android-base/thread_annotations.h>
25 #include <android/binder_auto_utils.h>
26 #include <android/binder_ibinder.h>
27 
28 #include <PendingRequestPool.h>
29 #include <VehicleUtils.h>
30 
31 #include <atomic>
32 #include <condition_variable>  // NOLINT
33 #include <memory>
34 #include <mutex>  // NOLINT
35 #include <unordered_map>
36 #include <unordered_set>
37 
38 namespace android {
39 namespace frameworks {
40 namespace automotive {
41 namespace vhal {
42 
43 namespace aidl_test {
44 
45 class AidlVhalClientTest;
46 
47 }  // namespace aidl_test
48 
49 class GetSetValueClient;
50 
51 class AidlVhalClient final : public IVhalClient {
52 public:
53     constexpr static char AIDL_VHAL_SERVICE[] =
54             "android.hardware.automotive.vehicle.IVehicle/default";
55 
56     static std::shared_ptr<IVhalClient> create();
57     static std::shared_ptr<IVhalClient> tryCreate();
58     static std::shared_ptr<IVhalClient> tryCreate(const char* descriptor);
59 
60     explicit AidlVhalClient(
61             std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> hal);
62 
63     AidlVhalClient(std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> hal,
64                    int64_t timeoutInMs);
65 
66     ~AidlVhalClient();
67 
68     bool isAidlVhal() override;
69 
70     std::unique_ptr<IHalPropValue> createHalPropValue(int32_t propId) override;
71 
72     std::unique_ptr<IHalPropValue> createHalPropValue(int32_t propId, int32_t areaId) override;
73 
74     void getValue(const IHalPropValue& requestValue,
75                   std::shared_ptr<GetValueCallbackFunc> callback) override;
76 
77     void setValue(const IHalPropValue& value,
78                   std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback) override;
79 
80     // Add the callback that would be called when VHAL binder died.
81     VhalClientResult<void> addOnBinderDiedCallback(
82             std::shared_ptr<OnBinderDiedCallbackFunc> callback) override;
83 
84     // Remove a previously added OnBinderDied callback.
85     VhalClientResult<void> removeOnBinderDiedCallback(
86             std::shared_ptr<OnBinderDiedCallbackFunc> callback) override;
87 
88     VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getAllPropConfigs() override;
89     VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getPropConfigs(
90             std::vector<int32_t> propIds) override;
91 
92     std::unique_ptr<ISubscriptionClient> getSubscriptionClient(
93             std::shared_ptr<ISubscriptionCallback> callback) override;
94 
95     int32_t getRemoteInterfaceVersion() override;
96 
97     // Converts a non-okay status to an error {@code Result}.
98     template <class T>
statusToError(const ndk::ScopedAStatus & status,const std::string & msg)99     inline static VhalClientResult<T> statusToError(const ndk::ScopedAStatus& status,
100                                                     const std::string& msg) {
101         using StatusCode = aidl::android::hardware::automotive::vehicle::StatusCode;
102         StatusCode statusCode = StatusCode::INTERNAL_ERROR;
103         if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
104             statusCode = static_cast<StatusCode>(status.getServiceSpecificError());
105         } else if (status.getExceptionCode() == EX_TRANSACTION_FAILED) {
106             if (status.getStatus() != STATUS_DEAD_OBJECT) {
107                 // STATUS_DEAD_OBJECT is fatal and should not return TRANSACTION_ERROR.
108                 return ClientStatusError(ErrorCode::TRANSACTION_ERROR)
109                         << msg << ", error: " << status.getDescription();
110             }
111         }
112         return ClientStatusError(statusCode) << msg << ", error: " << status.getDescription();
113     }
114 
115 private:
116     friend class aidl_test::AidlVhalClientTest;
117 
118     class ILinkUnlinkToDeath {
119     public:
120         virtual ~ILinkUnlinkToDeath() = default;
121         virtual binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
122                                             void* cookie) = 0;
123         virtual void deleteDeathRecipient(AIBinder_DeathRecipient* recipient) = 0;
124         virtual void setOnUnlinked(AIBinder_DeathRecipient* recipient,
125                                    AIBinder_DeathRecipient_onBinderUnlinked onUnlinked) = 0;
126     };
127 
128     class DefaultLinkUnlinkImpl final : public ILinkUnlinkToDeath {
129     public:
130         binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
131                                     void* cookie) override;
132         void deleteDeathRecipient(AIBinder_DeathRecipient* recipient) override;
133         void setOnUnlinked(AIBinder_DeathRecipient* recipient,
134                            AIBinder_DeathRecipient_onBinderUnlinked onUnlinked) override;
135     };
136 
137     std::atomic<int64_t> mRequestId = 0;
138     std::shared_ptr<GetSetValueClient> mGetSetValueClient;
139     std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> mHal;
140     std::unique_ptr<ILinkUnlinkToDeath> mLinkUnlinkImpl;
141     ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
142 
143     std::mutex mLock;
144     std::unordered_set<std::shared_ptr<OnBinderDiedCallbackFunc>> mOnBinderDiedCallbacks
145             GUARDED_BY(mLock);
146     std::condition_variable mDeathRecipientUnlinkedCv;
147     bool mDeathRecipientUnlinked GUARDED_BY(mLock) = false;
148 
149     static void onBinderDied(void* cookie);
150     static void onBinderUnlinked(void* cookie);
151 
152     void onBinderDiedWithContext();
153     void onBinderUnlinkedWithContext();
154 
155     VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> parseVehiclePropConfigs(
156             const aidl::android::hardware::automotive::vehicle::VehiclePropConfigs& configs);
157 
158     // Test-only functions:
159     AidlVhalClient(std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> hal,
160                    int64_t timeoutInMs, std::unique_ptr<ILinkUnlinkToDeath> linkUnlinkImpl);
161     size_t countOnBinderDiedCallbacks();
162 };
163 
164 class GetSetValueClient final :
165       public aidl::android::hardware::automotive::vehicle::BnVehicleCallback {
166 public:
167     struct PendingGetValueRequest {
168         std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback;
169         int32_t propId;
170         int32_t areaId;
171     };
172 
173     struct PendingSetValueRequest {
174         std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback;
175         int32_t propId;
176         int32_t areaId;
177     };
178 
179     GetSetValueClient(int64_t timeoutInNs,
180                       std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> mHal);
181 
182     ~GetSetValueClient();
183 
184     ndk::ScopedAStatus onGetValues(
185             const aidl::android::hardware::automotive::vehicle::GetValueResults& results) override;
186     ndk::ScopedAStatus onSetValues(
187             const aidl::android::hardware::automotive::vehicle::SetValueResults& results) override;
188     ndk::ScopedAStatus onPropertyEvent(
189             const aidl::android::hardware::automotive::vehicle::VehiclePropValues& values,
190             int32_t sharedMemoryCount) override;
191     ndk::ScopedAStatus onPropertySetError(
192             const aidl::android::hardware::automotive::vehicle::VehiclePropErrors& errors) override;
193     ndk::ScopedAStatus onSupportedValueChange(
194             const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&
195                     propIdAreaIds) override;
196 
197     void getValue(int64_t requestId, const IHalPropValue& requestValue,
198                   std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> clientCallback,
199                   std::shared_ptr<GetSetValueClient> vhalCallback);
200     void setValue(int64_t requestId, const IHalPropValue& requestValue,
201                   std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> clientCallback,
202                   std::shared_ptr<GetSetValueClient> vhalCallback);
203 
204 private:
205     std::mutex mLock;
206     std::unordered_map<int64_t, std::unique_ptr<PendingGetValueRequest>> mPendingGetValueCallbacks
207             GUARDED_BY(mLock);
208     std::unordered_map<int64_t, std::unique_ptr<PendingSetValueRequest>> mPendingSetValueCallbacks
209             GUARDED_BY(mLock);
210     std::unique_ptr<hardware::automotive::vehicle::PendingRequestPool> mPendingRequestPool;
211     std::shared_ptr<android::hardware::automotive::vehicle::PendingRequestPool::TimeoutCallbackFunc>
212             mOnGetValueTimeout;
213     std::shared_ptr<android::hardware::automotive::vehicle::PendingRequestPool::TimeoutCallbackFunc>
214             mOnSetValueTimeout;
215     std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> mHal;
216 
217     // Add a new GetValue pending request.
218     void addGetValueRequest(int64_t requestId, const IHalPropValue& requestValue,
219                             std::shared_ptr<AidlVhalClient::GetValueCallbackFunc> callback);
220     // Add a new SetValue pending request.
221     void addSetValueRequest(int64_t requestId, const IHalPropValue& requestValue,
222                             std::shared_ptr<AidlVhalClient::SetValueCallbackFunc> callback);
223     // Try to finish the pending GetValue request according to the requestId. If there is an
224     // existing pending request, the request would be finished and returned. Otherwise, if the
225     // request has already timed-out, nullptr would be returned.
226     std::unique_ptr<PendingGetValueRequest> tryFinishGetValueRequest(int64_t requestId);
227     // Try to finish the pending SetValue request according to the requestId. If there is an
228     // existing pending request, the request would be finished and returned. Otherwise, if the
229     // request has already timed-out, nullptr would be returned.
230     std::unique_ptr<PendingSetValueRequest> tryFinishSetValueRequest(int64_t requestId);
231 
232     template <class T>
233     std::unique_ptr<T> tryFinishRequest(int64_t requestId,
234                                         std::unordered_map<int64_t, std::unique_ptr<T>>* callbacks)
235             REQUIRES(mLock);
236 
237     void onGetValue(const aidl::android::hardware::automotive::vehicle::GetValueResult& result);
238     void onSetValue(const aidl::android::hardware::automotive::vehicle::SetValueResult& result);
239 
240     template <class T>
241     void onTimeout(const std::unordered_set<int64_t>& requestIds,
242                    std::unordered_map<int64_t, std::unique_ptr<T>>* callbacks);
243 };
244 
245 class SubscriptionVehicleCallback final :
246       public aidl::android::hardware::automotive::vehicle::BnVehicleCallback {
247 public:
248     explicit SubscriptionVehicleCallback(std::shared_ptr<ISubscriptionCallback> callback);
249 
250     ndk::ScopedAStatus onGetValues(
251             const aidl::android::hardware::automotive::vehicle::GetValueResults& results) override;
252     ndk::ScopedAStatus onSetValues(
253             const aidl::android::hardware::automotive::vehicle::SetValueResults& results) override;
254     ndk::ScopedAStatus onPropertyEvent(
255             const aidl::android::hardware::automotive::vehicle::VehiclePropValues& values,
256             int32_t sharedMemoryCount) override;
257     ndk::ScopedAStatus onPropertySetError(
258             const aidl::android::hardware::automotive::vehicle::VehiclePropErrors& errors) override;
259     ndk::ScopedAStatus onSupportedValueChange(
260             const std::vector<::aidl::android::hardware::automotive::vehicle::PropIdAreaId>&
261                     propIdAreaIds) override;
262 
263 private:
264     std::shared_ptr<ISubscriptionCallback> mCallback;
265 };
266 
267 class AidlSubscriptionClient final : public ISubscriptionClient {
268 public:
269     ~AidlSubscriptionClient() = default;
270 
271     AidlSubscriptionClient(
272             std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> hal,
273             std::shared_ptr<ISubscriptionCallback> callback);
274 
275     VhalClientResult<void> subscribe(
276             const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
277                     options) override;
278     VhalClientResult<void> unsubscribe(const std::vector<int32_t>& propIds) override;
279 
280 private:
281     std::shared_ptr<SubscriptionVehicleCallback> mSubscriptionCallback;
282     std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicle> mHal;
283 };
284 
285 }  // namespace vhal
286 }  // namespace automotive
287 }  // namespace frameworks
288 }  // namespace android
289 
290 #endif  // CPP_VHAL_CLIENT_INCLUDE_AIDLVHALCLIENT_H_
291