• 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 the client was not subscribed before, or one of the given property was not
99     // subscribed, or one of the property failed to unsubscribe. Caller is safe to retry since
100     // unsubscribing to an already unsubscribed property is okay (it would be ignored).
101     // Returns ok if all the requested properties for the client are unsubscribed.
102     VhalResult<void> unsubscribe(ClientIdType client, const std::vector<int32_t>& propIds);
103 
104     // Unsubscribes from all the properties for the client.
105     // Returns error if the client was not subscribed before or one of the subscribed properties
106     // for the client failed to unsubscribe. Caller is safe to retry.
107     // Returns ok if all the properties for the client are unsubscribed.
108     VhalResult<void> unsubscribe(ClientIdType client);
109 
110     // For a list of updated properties, returns a map that maps clients subscribing to
111     // the updated properties to a list of updated values. This would only return on-change property
112     // clients that should be informed for the given updated values.
113     std::unordered_map<CallbackType, std::vector<VehiclePropValue>> getSubscribedClients(
114             std::vector<VehiclePropValue>&& updatedValues);
115 
116     // For a list of set property error events, returns a map that maps clients subscribing to the
117     // properties to a list of errors for each client.
118     std::unordered_map<CallbackType,
119                        std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>>
120     getSubscribedClientsForErrorEvents(const std::vector<SetValueErrorEvent>& errorEvents);
121 
122     // Returns the number of subscribed clients.
123     size_t countClients();
124 
125     // Checks whether the sample rate is valid.
126     static bool checkSampleRateHz(float sampleRateHz);
127 
128     // Checks whether the resolution is valid.
129     static bool checkResolution(float resolution);
130 
131   private:
132     // Friend class for testing.
133     friend class DefaultVehicleHalTest;
134 
135     IVehicleHardware* mVehicleHardware;
136 
137     struct VehiclePropValueHashPropIdAreaId {
operatorVehiclePropValueHashPropIdAreaId138         inline size_t operator()(const VehiclePropValue& vehiclePropValue) const {
139             size_t res = 0;
140             hashCombine(res, vehiclePropValue.prop);
141             hashCombine(res, vehiclePropValue.areaId);
142             return res;
143         }
144     };
145 
146     struct VehiclePropValueEqualPropIdAreaId {
operatorVehiclePropValueEqualPropIdAreaId147         inline bool operator()(const VehiclePropValue& left, const VehiclePropValue& right) const {
148             return left.prop == right.prop && left.areaId == right.areaId;
149         }
150     };
151 
152     mutable std::mutex mLock;
153     std::unordered_map<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
154                        PropIdAreaIdHash>
155             mClientsByPropIdAreaId GUARDED_BY(mLock);
156     std::unordered_map<ClientIdType, std::unordered_set<PropIdAreaId, PropIdAreaIdHash>>
157             mSubscribedPropsByClient GUARDED_BY(mLock);
158     std::unordered_map<PropIdAreaId, ContSubConfigs, PropIdAreaIdHash> mContSubConfigsByPropIdArea
159             GUARDED_BY(mLock);
160     std::unordered_map<CallbackType,
161                        std::unordered_set<VehiclePropValue, VehiclePropValueHashPropIdAreaId,
162                                           VehiclePropValueEqualPropIdAreaId>>
163             mContSubValuesByCallback GUARDED_BY(mLock);
164 
165     VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId,
166                                                    const PropIdAreaId& propIdAreaId,
167                                                    float sampleRateHz, float resolution,
168                                                    bool enableVur) REQUIRES(mLock);
169     VhalResult<void> addOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId) REQUIRES(mLock);
170     // Removes the subscription client for the continuous [propId, areaId].
171     VhalResult<void> removeContinuousSubscriberLocked(const ClientIdType& clientId,
172                                                       const PropIdAreaId& propIdAreaId)
173             REQUIRES(mLock);
174     // Removes one subscription client for the on-change [propId, areaId].
175     VhalResult<void> removeOnChangeSubscriberLocked(const PropIdAreaId& propIdAreaId)
176             REQUIRES(mLock);
177 
178     VhalResult<void> updateContSubConfigsLocked(const PropIdAreaId& PropIdAreaId,
179                                                 const ContSubConfigs& newConfig) REQUIRES(mLock);
180 
181     VhalResult<void> unsubscribePropIdAreaIdLocked(SubscriptionManager::ClientIdType clientId,
182                                                    const PropIdAreaId& propIdAreaId)
183             REQUIRES(mLock);
184 
185     // Checks whether the manager is empty. For testing purpose.
186     bool isEmpty();
187 
188     bool isValueUpdatedLocked(const CallbackType& callback, const VehiclePropValue& value)
189             REQUIRES(mLock);
190 
191     // Get the interval in nanoseconds accroding to sample rate.
192     static android::base::Result<int64_t> getIntervalNanos(float sampleRateHz);
193 };
194 
195 }  // namespace vehicle
196 }  // namespace automotive
197 }  // namespace hardware
198 }  // namespace android
199 
200 #endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_
201