• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_
18 #define android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_
19 
20 #include <IVehicleHardware.h>
21 #include <VehicleHalTypes.h>
22 #include <VehicleUtils.h>
23 
24 #include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
25 #include <android-base/result.h>
26 #include <android-base/thread_annotations.h>
27 
28 #include <cmath>
29 #include <limits>
30 #include <mutex>
31 #include <optional>
32 #include <unordered_map>
33 #include <unordered_set>
34 #include <vector>
35 
36 namespace android {
37 namespace hardware {
38 namespace automotive {
39 namespace vehicle {
40 
41 // A structure to represent subscription config for one subscription client.
42 struct SubConfig {
43     float sampleRateHz;
44     float resolution;
45     bool enableVur;
46 };
47 
48 // A class to represent all the subscription configs for a continuous [propId, areaId].
49 class ContSubConfigs final {
50   public:
51     using ClientIdType = const AIBinder*;
52 
53     void addClient(const ClientIdType& clientId, const SubConfig& subConfig);
54     void removeClient(const ClientIdType& clientId);
55     float getMaxSampleRateHz() const;
56     float getMinRequiredResolution() const;
57     bool isVurEnabled() const;
58     bool isVurEnabledForClient(const ClientIdType& clientId) const;
59     float getResolutionForClient(const ClientIdType& clientId) const;
60 
61   private:
62     float mMaxSampleRateHz = 0.;
63     // Baseline for resolution is maximum possible float. We want to sanitize to the highest
64     // requested resolution, which is the smallest float value for resolution.
65     float mMinRequiredResolution = std::numeric_limits<float>::max();
66     bool mEnableVur;
67     std::unordered_map<ClientIdType, SubConfig> mConfigByClient;
68 
69     void refreshCombinedConfig();
70 };
71 
72 // A thread-safe subscription manager that manages all VHAL subscriptions.
73 class SubscriptionManager final {
74   public:
75     using ClientIdType = const AIBinder*;
76     using CallbackType =
77             std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
78     using VehiclePropValue = aidl::android::hardware::automotive::vehicle::VehiclePropValue;
79 
80     explicit SubscriptionManager(IVehicleHardware* vehicleHardware);
81     ~SubscriptionManager();
82 
83     // Subscribes to properties according to {@code SubscribeOptions}. Note that all option must
84     // contain non-empty areaIds field, which contains all area IDs to subscribe. As a result,
85     // the options here is different from the options passed from VHAL client.
86     // Returns error if any of the subscribe options is not valid or one of the properties failed
87     // to subscribe. Part of the properties maybe be subscribed successfully if this function
88     // returns error. Caller is safe to retry since subscribing to an already subscribed property
89     // is okay.
90     // Returns ok if all the options are parsed correctly and all the properties are subscribed.
91     VhalResult<void> subscribe(
92             const CallbackType& callback,
93             const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
94                     options,
95             bool isContinuousProperty);
96 
97     // Unsubscribes from the properties for the client.
98     // Returns error if one of the property failed to unsubscribe. Caller is safe to retry since
99     // unsubscribing to an already unsubscribed property is okay (it would be ignored).
100     // Returns ok if all the requested properties for the client are unsubscribed.
101     VhalResult<void> unsubscribe(ClientIdType client, const std::vector<int32_t>& propIds);
102 
103     // Unsubscribes from all the properties for the client.
104     // Returns error one of the subscribed properties for the client failed to unsubscribe.
105     // Caller is safe to retry.
106     // Returns ok if all the properties for the client are unsubscribed.
107     VhalResult<void> unsubscribe(ClientIdType client);
108 
109     // For a list of updated properties, returns a map that maps clients subscribing to
110     // the updated properties to a list of updated values. This would only return on-change property
111     // clients that should be informed for the given updated values.
112     std::unordered_map<CallbackType, std::vector<VehiclePropValue>> getSubscribedClients(
113             std::vector<VehiclePropValue>&& updatedValues);
114 
115     // For a list of set property error events, returns a map that maps clients subscribing to the
116     // properties to a list of errors for each client.
117     std::unordered_map<CallbackType,
118                        std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>>
119     getSubscribedClientsForErrorEvents(const std::vector<SetValueErrorEvent>& errorEvents);
120 
121     // For a list of [propId, areaId]s that has updated supported value, returns a map that maps
122     // subscribing clients to updated [propId, areaId]s.
123     std::unordered_map<CallbackType, std::vector<PropIdAreaId>>
124     getSubscribedClientsForSupportedValueChange(const std::vector<PropIdAreaId>& propIdAreaIds);
125 
126     // Subscribes to supported values change.
127     VhalResult<void> subscribeSupportedValueChange(const CallbackType& callback,
128                                                    const std::vector<PropIdAreaId>& propIdAreaIds);
129 
130     // Unsubscribes to supported values change.
131     VhalResult<void> unsubscribeSupportedValueChange(
132             ClientIdType client, const std::vector<PropIdAreaId>& propIdAreaIds);
133 
134     // Returns the number of subscribed property change clients.
135     size_t countPropertyChangeClients();
136 
137     // Returns the number of subscribed supported value change clients.
138     size_t countSupportedValueChangeClients();
139 
140     // Checks whether the sample rate is valid.
141     static bool checkSampleRateHz(float sampleRateHz);
142 
143     // Checks whether the resolution is valid.
144     static bool checkResolution(float resolution);
145 
146   private:
147     // Friend class for testing.
148     friend class DefaultVehicleHalTest;
149     friend class SubscriptionManagerTest;
150 
151     IVehicleHardware* mVehicleHardware;
152 
153     struct VehiclePropValueHashPropIdAreaId {
operatorVehiclePropValueHashPropIdAreaId154         inline size_t operator()(const VehiclePropValue& vehiclePropValue) const {
155             size_t res = 0;
156             hashCombine(res, vehiclePropValue.prop);
157             hashCombine(res, vehiclePropValue.areaId);
158             return res;
159         }
160     };
161 
162     struct VehiclePropValueEqualPropIdAreaId {
operatorVehiclePropValueEqualPropIdAreaId163         inline bool operator()(const VehiclePropValue& left, const VehiclePropValue& right) const {
164             return left.prop == right.prop && left.areaId == right.areaId;
165         }
166     };
167 
168     mutable std::mutex mLock;
169     std::unordered_map<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
170                        PropIdAreaIdHash>
171             mClientsByPropIdAreaId GUARDED_BY(mLock);
172     std::unordered_map<ClientIdType, std::unordered_set<PropIdAreaId, PropIdAreaIdHash>>
173             mSubscribedPropsByClient GUARDED_BY(mLock);
174     std::unordered_map<PropIdAreaId, ContSubConfigs, PropIdAreaIdHash> mContSubConfigsByPropIdArea
175             GUARDED_BY(mLock);
176     std::unordered_map<CallbackType,
177                        std::unordered_set<VehiclePropValue, VehiclePropValueHashPropIdAreaId,
178                                           VehiclePropValueEqualPropIdAreaId>>
179             mContSubValuesByCallback GUARDED_BY(mLock);
180     std::unordered_map<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
181                        PropIdAreaIdHash>
182             mSupportedValueChangeClientsByPropIdAreaId GUARDED_BY(mLock);
183     std::unordered_map<ClientIdType, std::unordered_set<PropIdAreaId, PropIdAreaIdHash>>
184             mSupportedValueChangePropIdAreaIdsByClient GUARDED_BY(mLock);
185 
186     VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId,
187                                                    const PropIdAreaId& propIdAreaId,
188                                                    float sampleRateHz, float resolution,
189                                                    bool enableVur) REQUIRES(mLock);
190     VhalResult<void> addOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId) REQUIRES(mLock);
191     // Removes the subscription client for the continuous [propId, areaId].
192     VhalResult<void> removeContinuousSubscriberLocked(const ClientIdType& clientId,
193                                                       const PropIdAreaId& propIdAreaId)
194             REQUIRES(mLock);
195     // Removes one subscription client for the on-change [propId, areaId].
196     VhalResult<void> removeOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId)
197             REQUIRES(mLock);
198 
199     VhalResult<void> updateContSubConfigsLocked(const PropIdAreaId& PropIdAreaId,
200                                                 const ContSubConfigs& newConfig) REQUIRES(mLock);
201 
202     VhalResult<void> unsubscribePropIdAreaIdLocked(SubscriptionManager::ClientIdType clientId,
203                                                    const PropIdAreaId& propIdAreaId)
204             REQUIRES(mLock);
205     VhalResult<void> unsubscribeSupportedValueChangeLocked(
206             SubscriptionManager::ClientIdType clientId,
207             const std::vector<PropIdAreaId>& propIdAreaIds) REQUIRES(mLock);
208 
209     // Checks whether the manager is empty. For testing purpose.
210     bool isEmpty();
211 
212     bool isValueUpdatedLocked(const CallbackType& callback, const VehiclePropValue& value)
213             REQUIRES(mLock);
214 
215     // Get the interval in nanoseconds accroding to sample rate.
216     static android::base::Result<int64_t> getIntervalNanos(float sampleRateHz);
217 };
218 
219 }  // namespace vehicle
220 }  // namespace automotive
221 }  // namespace hardware
222 }  // namespace android
223 
224 #endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_
225