1 /* 2 * Copyright (C) 2016 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 CHRE_CORE_WIFI_REQUEST_MANAGER_H_ 18 #define CHRE_CORE_WIFI_REQUEST_MANAGER_H_ 19 20 #include "chre/core/nanoapp.h" 21 #include "chre/platform/platform_wifi.h" 22 #include "chre/util/non_copyable.h" 23 24 namespace chre { 25 26 /** 27 * The WifiRequestManager handles requests from nanoapps for Wifi information. 28 * This includes multiplexing multiple requests into one for the platform to 29 * handle. 30 * 31 * This class is effectively a singleton as there can only be one instance of 32 * the PlatformWifi instance. 33 */ 34 class WifiRequestManager : public NonCopyable { 35 public: 36 /** 37 * Initializes the WifiRequestManager with a default state and memory for any 38 * requests. 39 */ 40 WifiRequestManager(); 41 42 /** 43 * @return the WiFi capabilities exposed by this platform. 44 */ 45 uint32_t getCapabilities(); 46 47 /** 48 * Handles a request from a nanoapp to configure the scan monitor. This 49 * includes merging multiple requests for scan monitoring to the PAL (ie: if 50 * multiple apps enable the scan monitor the PAL is only enabled once). 51 * 52 * @param nanoapp The nanoapp that has requested that the scan monitor be 53 * configured. 54 * @param enable true to enable scan monitoring, false to disable scan 55 * monitoring. 56 * @param cookie A cookie that is round-tripped back to the nanoapp to 57 * provide a context when making the request. 58 * @return true if the request was accepted. The result is delivered 59 * asynchronously through a CHRE event. 60 */ 61 bool configureScanMonitor(Nanoapp *nanoapp, bool enable, const void *cookie); 62 63 /** 64 * Performs an active wifi scan. 65 * 66 * This is currently a 1:1 mapping into the PAL. If more than one nanoapp 67 * requests an active wifi scan, this will be an assertion failure for debug 68 * builds and a no-op in production (ie: subsequent requests are ignored). 69 * 70 * @param nanoapp The nanoapp that has requested an active wifi scan. 71 * @param params The parameters of the wifi scan. 72 * @param cookie A cookie that is round-tripped back to the nanoapp to provide 73 * a context when making the request. 74 * @return true if the request was accepted. The result is delivered 75 * asynchronously through a CHRE event. 76 */ 77 bool requestScan(Nanoapp *nanoapp, const chreWifiScanParams *params, 78 const void *cookie); 79 80 /** 81 * Handles the result of a request to PlatformWifi to change the state of the 82 * scan monitor. 83 * 84 * @param enabled true if the result of the operation was an enabled scan 85 * monitor. 86 * @param errorCode an error code that is provided to indicate success or what 87 * type of error has occurred. See the chreError enum in the CHRE API 88 * for additional details. 89 */ 90 void handleScanMonitorStateChange(bool enabled, uint8_t errorCode); 91 92 /** 93 * Handles the result of a request to the PlatformWifi to request an active 94 * Wifi scan. 95 * 96 * @param pending The result of the request was successful and the results 97 * be sent via the handleScanEvent method. 98 * @param errorCode an error code that is used to indicate success or what 99 * type of error has occurred. See the chreError enum in the CHRE API 100 * for additional details. 101 */ 102 void handleScanResponse(bool pending, uint8_t errorCode); 103 104 /** 105 * Handles a CHRE wifi scan event. 106 * 107 * @param event The wifi scan event provided to the wifi request manager. This 108 * memory is guaranteed not to be modified until it has been explicitly 109 * released through the PlatformWifi instance. 110 */ 111 void handleScanEvent(chreWifiScanEvent *event); 112 113 private: 114 /** 115 * Tracks the state of the wifi scan monitor. 116 */ 117 struct ScanMonitorStateTransition { 118 //! The nanoapp instance ID that prompted the change. 119 uint32_t nanoappInstanceId; 120 121 //! The cookie provided to the CHRE API when the nanoapp requested a change 122 //! of state to the scan monitoring. 123 const void *cookie; 124 125 //! The target state of the PAL scan monitor. 126 bool enable; 127 }; 128 129 //! The maximum number of scan monitor state transitions that can be queued. 130 static constexpr size_t kMaxScanMonitorStateTransitions = 8; 131 132 //! The instance of the platform wifi interface. 133 PlatformWifi mPlatformWifi; 134 135 //! The queue of state transition requests for the scan monitor. Only one 136 //! asynchronous scan monitor state transition can be in flight at one time. 137 //! Any further requests are queued here. 138 ArrayQueue<ScanMonitorStateTransition, 139 kMaxScanMonitorStateTransitions> mScanMonitorStateTransitions; 140 141 //! The list of nanoapps who have enabled scan monitoring. This list is 142 //! maintained to ensure that nanoapps are always subscribed to wifi scan 143 //! results as requested. Note that a request for wifi scan monitoring can 144 //! exceed the duration of a single active wifi scan request. This makes it 145 //! insuitable only subscribe to wifi scan events when an active request is 146 //! made and the scan monitor must remain enabled when an active request has 147 //! completed. 148 DynamicVector<uint32_t> mScanMonitorNanoapps; 149 150 // TODO: Support multiple requests for active wifi scans. 151 //! The instance ID of the nanoapp that has a pending active scan request. At 152 //! this time, only one nanoapp can have a pending request for an active WiFi 153 //! scan. 154 Optional<uint32_t> mScanRequestingNanoappInstanceId; 155 156 //! The cookie passed in by a nanoapp making an active request for wifi scans. 157 //! Note that this will only be valid if the mScanRequestingNanoappInstanceId 158 //! is set. 159 const void *mScanRequestingNanoappCookie; 160 161 //! This is set to true if the results of an active scan request are pending. 162 bool mScanRequestResultsArePending = false; 163 164 //! Accumulates the number of scan event results to determine when the last 165 //! in a scan event stream has been received. 166 uint8_t mScanEventResultCountAccumulator = 0; 167 168 /** 169 * @return true if the scan monitor is enabled by any nanoapps. 170 */ 171 bool scanMonitorIsEnabled() const; 172 173 /** 174 * @param instanceId the instance ID of the nanoapp. 175 * @param index an optional pointer to a size_t to populate with the index of 176 * the nanoapp in the list of nanoapps. 177 * @return true if the nanoapp has an active request for scan monitoring. 178 */ 179 bool nanoappHasScanMonitorRequest(uint32_t instanceId, 180 size_t *index = nullptr) const; 181 182 /** 183 * @param requestedState The requested state to compare against. 184 * @param nanoappHasRequest The requesting nanoapp has an existing request. 185 * @return true if the scan monitor is in the requested state. 186 */ 187 bool scanMonitorIsInRequestedState(bool requestedState, 188 bool nanoappHasRequest) const; 189 190 /** 191 * @param requestedState The requested state to compare against. 192 * @param nanoappHasRequest The requesting nanoapp has an existing request. 193 * @return true if a state transition is required to reach the requested 194 * state. 195 */ 196 bool scanMonitorStateTransitionIsRequired(bool requestedState, 197 bool nanoappHasRequest) const; 198 199 /** 200 * Builds a scan monitor state transition and adds it to the queue of incoming 201 * requests. 202 * @param nanoapp A non-null pointer to a nanoapp that is requesting the 203 * change. 204 * @param enable The target requested scan monitoring state. 205 * @param cookie The pointer cookie passed in by the calling nanoapp to return 206 * to the nanoapp when the request completes. 207 * @return true if the request is enqueued or false if the queue is full. 208 */ 209 bool addScanMonitorRequestToQueue(Nanoapp *nanoapp, bool enable, 210 const void *cookie); 211 212 /** 213 * Adds a nanoapp to the list of nanoapps that are monitoring for wifi scans. 214 * @param enable true if enabling scan monitoring. 215 * @param instanceId The instance ID of the scan monitoring nanoapp. 216 * @return true if the nanoapp was added to the list. 217 */ 218 bool updateNanoappScanMonitoringList(bool enable, uint32_t instanceId); 219 220 /** 221 * Posts an event to a nanoapp indicating the result of a wifi scan monitoring 222 * configuration change. 223 * 224 * @param nanoappInstanceId The nanoapp instance ID to direct the event to. 225 * @param success If the request for a wifi resource was successful. 226 * @param enable The target state of the request. If enable is set to false 227 * and the request was successful, the nanoapp is removed from the 228 * list of nanoapps requesting scan monitoring. 229 * @param errorCode The error code when success is set to false. 230 * @param cookie The cookie to be provided to the nanoapp. This is 231 * round-tripped from the nanoapp to provide context. 232 * @return true if the event was successfully posted to the event loop. 233 */ 234 bool postScanMonitorAsyncResultEvent( 235 uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode, 236 const void *cookie); 237 238 /** 239 * Calls through to postScanMonitorAsyncResultEvent but invokes the 240 * FATAL_ERROR macro if the event is not posted successfully. This is used in 241 * asynchronous contexts where a nanoapp could be stuck waiting for a response 242 * but CHRE failed to enqueue one. For parameter details, 243 * @see postScanMonitorAsyncResultEvent 244 */ 245 void postScanMonitorAsyncResultEventFatal( 246 uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode, 247 const void *cookie); 248 249 /** 250 * Posts an event to a nanoapp indicating the result of a request for an 251 * active wifi scan. 252 * 253 * @param nanoappInstanceId The nanoapp instance ID to direct the event to. 254 * @param success If the request for a wifi resource was successful. 255 * @param errorCode The error code when success is set to false. 256 * @param cookie The cookie to be provided to the nanoapp. This is 257 * round-tripped from the nanoapp to provide context. 258 * @return true if the event was successfully posted to the event loop. 259 */ 260 bool postScanRequestAsyncResultEvent( 261 uint32_t nanoappInstanceId, bool success, uint8_t errorCode, 262 const void *cookie); 263 264 /** 265 * Calls through to postScanRequestAsyncResultEvent but invokes the 266 * FATAL_ERROR macro if the event is not posted successfully. This is used in 267 * asynchronous contexts where a nanoapp could be stuck waiting for a response 268 * but CHRE failed to enqueue one. For parameter details, 269 * @see postScanRequestAsyncResultEvent 270 */ 271 void postScanRequestAsyncResultEventFatal( 272 uint32_t nanoappInstanceId, bool success, uint8_t errorCode, 273 const void *cookie); 274 275 /** 276 * Posts a broadcast event containing the results of a wifi scan. Failure to 277 * post this event is a FATAL_ERROR. This is unrecoverable as the nanoapp will 278 * be stuck waiting for wifi scan results but there may be a gap. 279 * 280 * @param event the wifi scan event. 281 */ 282 void postScanEventFatal(chreWifiScanEvent *event); 283 284 /** 285 * Handles the result of a request to PlatformWifi to change the state of the 286 * scan monitor. See the handleScanMonitorStateChange method which may be 287 * called from any thread. This method is intended to be invoked on the CHRE 288 * event loop thread. 289 * 290 * @param enabled true if the result of the operation was an enabled scan 291 * monitor. 292 * @param errorCode an error code that is provided to indicate success or what 293 * type of error has occurred. See the chreError enum in the CHRE API 294 * for additional details. 295 */ 296 void handleScanMonitorStateChangeSync(bool enabled, uint8_t errorCode); 297 298 /** 299 * Handles the result of a request to PlatformWifi to perform an active WiFi 300 * scan. See the handleScanResponse method which may be called from any 301 * thread. This method is intended to be invoked on the CHRE event loop 302 * thread. 303 * 304 * @param enabled true if the result of the operation was an enabled scan 305 * monitor. 306 * @param errorCode an error code that is provided to indicate success or what 307 * type of error has occurred. See the chreError enum in the CHRE API 308 * for additional details. 309 */ 310 void handleScanResponseSync(bool pending, uint8_t errorCode); 311 312 /** 313 * Handles a WiFi scan event. See the handleScanEvent method with may be 314 * called from any thread. This method is intended to be invoked on the CHRE 315 * event loop thread. 316 * 317 * @param event The wifi event to distribute to nanoapps. 318 */ 319 void handleScanEventSync(chreWifiScanEvent *event); 320 321 /** 322 * TODO: this. 323 */ 324 void handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent); 325 326 /** 327 * Releases the memory associated with an asynchronous wifi event. 328 * 329 * @param eventType The type of event being freed. 330 * @param eventData A pointer to the data to release. 331 */ 332 static void freeWifiAsyncResultCallback(uint16_t eventType, void *eventData); 333 334 /** 335 * Releases a wifi scan event after nanoapps have consumed it. 336 * 337 * @param eventType the type of event being freed. 338 * @param eventData a pointer to the scan event to release. 339 */ 340 static void freeWifiScanEventCallback(uint16_t eventType, void *eventData); 341 }; 342 343 } // namespace chre 344 345 #endif // CHRE_CORE_WIFI_REQUEST_MANAGER_H_ 346