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