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