• 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_IVHALCLIENT_H_
18 #define CPP_VHAL_CLIENT_INCLUDE_IVHALCLIENT_H_
19 
20 #include "IHalPropConfig.h"
21 #include "IHalPropValue.h"
22 
23 #include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
24 #include <aidl/android/hardware/automotive/vehicle/SubscribeOptions.h>
25 #include <android-base/result.h>
26 
27 #include <VehicleUtils.h>
28 
29 namespace android {
30 namespace frameworks {
31 namespace automotive {
32 namespace vhal {
33 
34 struct HalPropError {
35     int32_t propId;
36     int32_t areaId;
37     aidl::android::hardware::automotive::vehicle::StatusCode status;
38 };
39 
40 // ISubscriptionCallback is a general interface to delivery property events caused by subscription.
41 class ISubscriptionCallback {
42 public:
43     virtual ~ISubscriptionCallback() = default;
44     /**
45      * Called when new property events happen.
46      */
47     virtual void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) = 0;
48 
49     /**
50      * Called when property set errors happen.
51      */
52     virtual void onPropertySetError(const std::vector<HalPropError>& errors) = 0;
53 };
54 
55 // Errors for vehicle HAL client interface.
56 enum class ErrorCode : int {
57     // Response status is OK. No errors.
58     OK = 0,
59     // The argument is invalid.
60     INVALID_ARG = 1,
61     // The request timed out. The client may try again.
62     TIMEOUT = 2,
63     // Some errors occur while connecting VHAL. The client may try again.
64     TRANSACTION_ERROR = 3,
65     // Some unexpected errors happen in VHAL. Needs to try again.
66     TRY_AGAIN_FROM_VHAL = 4,
67     // The device of corresponding vehicle property is not available.
68     // Example: the HVAC unit is turned OFF when user wants to adjust temperature.
69     NOT_AVAILABLE_FROM_VHAL = 5,
70     // The request is unauthorized.
71     ACCESS_DENIED_FROM_VHAL = 6,
72     // Some unexpected errors, for example OOM, happen in VHAL.
73     INTERNAL_ERROR_FROM_VHAL = 7,
74 };
75 
76 // Convert the VHAL {@code StatusCode} to {@code ErrorCode}.
statusCodeToErrorCode(const aidl::android::hardware::automotive::vehicle::StatusCode & code)77 static ErrorCode statusCodeToErrorCode(
78         const aidl::android::hardware::automotive::vehicle::StatusCode& code) {
79     switch (code) {
80         case aidl::android::hardware::automotive::vehicle::StatusCode::OK:
81             return ErrorCode::OK;
82         case aidl::android::hardware::automotive::vehicle::StatusCode::TRY_AGAIN:
83             return ErrorCode::TRY_AGAIN_FROM_VHAL;
84         case aidl::android::hardware::automotive::vehicle::StatusCode::INVALID_ARG:
85             return ErrorCode::INVALID_ARG;
86         case aidl::android::hardware::automotive::vehicle::StatusCode::NOT_AVAILABLE:
87             return ErrorCode::NOT_AVAILABLE_FROM_VHAL;
88         case aidl::android::hardware::automotive::vehicle::StatusCode::ACCESS_DENIED:
89             return ErrorCode::ACCESS_DENIED_FROM_VHAL;
90         case aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR:
91             return ErrorCode::INTERNAL_ERROR_FROM_VHAL;
92         default:
93             return ErrorCode::INTERNAL_ERROR_FROM_VHAL;
94     }
95 }
96 
97 // VhalClientError is a wrapper class for {@code ErrorCode} that could act as E in {@code
98 // Result<T,E>}.
99 class VhalClientError final {
100 public:
VhalClientError()101     VhalClientError() : mCode(ErrorCode::OK) {}
102 
VhalClientError(ErrorCode && code)103     VhalClientError(ErrorCode&& code) : mCode(code) {}
104 
VhalClientError(const ErrorCode & code)105     VhalClientError(const ErrorCode& code) : mCode(code) {}
106 
VhalClientError(aidl::android::hardware::automotive::vehicle::StatusCode && code)107     VhalClientError(aidl::android::hardware::automotive::vehicle::StatusCode&& code) :
108           mCode(statusCodeToErrorCode(code)) {}
109 
VhalClientError(const aidl::android::hardware::automotive::vehicle::StatusCode & code)110     VhalClientError(const aidl::android::hardware::automotive::vehicle::StatusCode& code) :
111           mCode(statusCodeToErrorCode(code)) {}
112 
113     ErrorCode value() const;
114 
ErrorCode()115     inline operator ErrorCode() const { return value(); }
116 
117     static std::string toString(ErrorCode code);
118 
119     std::string print() const;
120 
121 private:
122     ErrorCode mCode;
123 };
124 
125 // VhalClientResult is a {@code Result} that contains {@code ErrorCode} as error type.
126 template <class T>
127 using VhalClientResult = android::base::Result<T, VhalClientError>;
128 
129 // ClientStatusError could be cast to {@code ResultError} with a {@code ErrorCode}
130 // and should be used as error type for {@VhalClientResult}.
131 using ClientStatusError = android::base::Error<VhalClientError>;
132 
133 // ISubscriptionCallback is a client that could be used to subscribe/unsubscribe.
134 class ISubscriptionClient {
135 public:
136     virtual ~ISubscriptionClient() = default;
137 
138     virtual VhalClientResult<void> subscribe(
139             const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
140                     options) = 0;
141 
142     virtual VhalClientResult<void> unsubscribe(const std::vector<int32_t>& propIds) = 0;
143 };
144 
145 // IVhalClient is a thread-safe client for AIDL or HIDL VHAL backend.
146 class IVhalClient {
147 public:
148     // Wait for VHAL service and create a client. Return nullptr if failed to connect to VHAL.
149     static std::shared_ptr<IVhalClient> create();
150 
151     // Try to get the VHAL service and create a client. Return nullptr if failed to connect to VHAL.
152     static std::shared_ptr<IVhalClient> tryCreate();
153 
154     // Try to create a client based on the AIDL VHAL service descriptor.
155     static std::shared_ptr<IVhalClient> tryCreateAidlClient(const char* descriptor);
156 
157     // Try to create a client based on the HIDL VHAL service descriptor.
158     static std::shared_ptr<IVhalClient> tryCreateHidlClient(const char* descriptor);
159 
160     // The default timeout for callbacks.
161     constexpr static int64_t DEFAULT_TIMEOUT_IN_SEC = 10;
162 
163     virtual ~IVhalClient() = default;
164 
165     using GetValueCallbackFunc =
166             std::function<void(VhalClientResult<std::unique_ptr<IHalPropValue>>)>;
167     using SetValueCallbackFunc = std::function<void(VhalClientResult<void>)>;
168     using OnBinderDiedCallbackFunc = std::function<void()>;
169 
170     /**
171      * Check whether we are connected to AIDL VHAL backend.
172      *
173      * Returns {@code true} if we are connected to AIDL VHAL backend, {@code false} if we are
174      * connected to HIDL backend.
175      */
176     virtual bool isAidlVhal() = 0;
177 
178     /**
179      * Create a new {@code IHalpropValue}.
180      *
181      * @param propId The property ID.
182      * @return The created {@code IHalPropValue}.
183      */
184     virtual std::unique_ptr<IHalPropValue> createHalPropValue(int32_t propId) = 0;
185 
186     /**
187      * Create a new {@code IHalpropValue}.
188      *
189      * @param propId The property ID.
190      * @param areaId The area ID for the property.
191      * @return The created {@code IHalPropValue}.
192      */
193     virtual std::unique_ptr<IHalPropValue> createHalPropValue(int32_t propId, int32_t areaId) = 0;
194 
195     /**
196      * Get a property value asynchronously.
197      *
198      * @param requestValue The value to request.
199      * @param callback The callback that would be called when the result is ready. The callback
200      *    would be called with an okay result with the got value inside on success. The callback
201      *    would be called with an error result with error code as the returned status code on
202      *    failure.
203      */
204     virtual void getValue(const IHalPropValue& requestValue,
205                           std::shared_ptr<GetValueCallbackFunc> callback) = 0;
206 
207     /**
208      * Get a property value synchronously.
209      *
210      * @param requestValue the value to request.
211      * @return An okay result with the returned value on success or an error result with returned
212      *    status code as error code. For AIDL backend, this would return TRY_AGAIN error on timeout.
213      *    For HIDL backend, because HIDL backend is synchronous, timeout does not apply.
214      */
215     virtual VhalClientResult<std::unique_ptr<IHalPropValue>> getValueSync(
216             const IHalPropValue& requestValue);
217 
218     /**
219      * Set a property value asynchronously.
220      *
221      * @param requestValue The value to set.
222      * @param callback The callback that would be called when the request is processed. The callback
223      *    would be called with an empty okay result on success. The callback would be called with
224      *    an error result with error code as the returned status code on failure.
225      */
226     virtual void setValue(const IHalPropValue& requestValue,
227                           std::shared_ptr<SetValueCallbackFunc> callback) = 0;
228 
229     /**
230      * Set a property value synchronously.
231      *
232      * @param requestValue the value to set.
233      * @return An empty okay result on success or an error result with returned status code as
234      *    error code. For AIDL backend, this would return TIMEOUT error on timeout.
235      *    For HIDL backend, because HIDL backend is synchronous, timeout does not apply.
236      */
237     virtual VhalClientResult<void> setValueSync(const IHalPropValue& requestValue);
238 
239     /**
240      * Add a callback that would be called when the binder connection to VHAL died.
241      *
242      * @param callback The callback that would be called when the binder died.
243      * @return An okay result on success or an error on failure.
244      */
245     virtual VhalClientResult<void> addOnBinderDiedCallback(
246             std::shared_ptr<OnBinderDiedCallbackFunc> callback) = 0;
247 
248     /**
249      * Remove a previously added OnBinderDied callback.
250      *
251      * @param callback The callback that would be removed.
252      * @return An okay result on success, or an error if the callback is not added before.
253      */
254     virtual VhalClientResult<void> removeOnBinderDiedCallback(
255             std::shared_ptr<OnBinderDiedCallbackFunc> callback) = 0;
256 
257     /**
258      * Get all the property configurations.
259      *
260      * @return An okay result that contains all property configs on success or an error on failure.
261      */
262     virtual VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getAllPropConfigs() = 0;
263 
264     /**
265      * Get the configs for specified properties.
266      *
267      * @param propIds A list of property IDs to get configs for.
268      * @return An okay result that contains property configs for specified properties on success or
269      *    an error if failed to get any of the property configs.
270      */
271     virtual VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getPropConfigs(
272             std::vector<int32_t> propIds) = 0;
273 
274     /**
275      * Get a {@code ISubscriptionClient} that could be used to subscribe/unsubscribe to properties.
276      *
277      * @param callback The callback that would be called when property event happens.
278      * @return A {@code ISubscriptionClient} used to subscribe/unsubscribe.
279      */
280     virtual std::unique_ptr<ISubscriptionClient> getSubscriptionClient(
281             std::shared_ptr<ISubscriptionCallback> callback) = 0;
282 };
283 
284 }  // namespace vhal
285 }  // namespace automotive
286 }  // namespace frameworks
287 }  // namespace android
288 
289 #endif  // CPP_VHAL_CLIENT_INCLUDE_IVHALCLIENT_H_
290