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/buffer.h" 23 #include "chre/util/non_copyable.h" 24 #include "chre/util/optional.h" 25 #include "chre/util/time.h" 26 #include "chre_api/chre/wifi.h" 27 28 namespace chre { 29 30 /** 31 * The WifiRequestManager handles requests from nanoapps for Wifi information. 32 * This includes multiplexing multiple requests into one for the platform to 33 * handle. 34 * 35 * This class is effectively a singleton as there can only be one instance of 36 * the PlatformWifi instance. 37 */ 38 class WifiRequestManager : public NonCopyable { 39 public: 40 /** 41 * Initializes the WifiRequestManager with a default state and memory for any 42 * requests. 43 */ 44 WifiRequestManager(); 45 46 /** 47 * Initializes the underlying platform-specific WiFi module. Must be called 48 * prior to invoking any other methods in this class. 49 */ 50 void init(); 51 52 /** 53 * @return the WiFi capabilities exposed by this platform. 54 */ 55 uint32_t getCapabilities(); 56 57 /** 58 * Handles a request from a nanoapp to configure the scan monitor. This 59 * includes merging multiple requests for scan monitoring to the PAL (ie: if 60 * multiple apps enable the scan monitor the PAL is only enabled once). 61 * 62 * @param nanoapp The nanoapp that has requested that the scan monitor be 63 * configured. 64 * @param enable true to enable scan monitoring, false to disable scan 65 * monitoring. 66 * @param cookie A cookie that is round-tripped back to the nanoapp to 67 * provide a context when making the request. 68 * 69 * @return true if the request was accepted. The result is delivered 70 * asynchronously through a CHRE event. 71 */ 72 bool configureScanMonitor(Nanoapp *nanoapp, bool enable, const void *cookie); 73 74 /** 75 * Handles a nanoapp's request for RTT ranging against a set of devices. 76 * 77 * @param nanoapp Nanoapp issuing the request. 78 * @param params Non-null pointer to parameters, supplied by the nanoapp via 79 * chreWifiRequestRangingAsync() 80 * @param cookie Opaque pointer supplied by the nanoapp and passed back in the 81 * async result. 82 * 83 * @return true if the request was accepted. The result is delivered 84 * asynchronously through a CHRE event. 85 */ 86 bool requestRanging(Nanoapp *nanoapp, const chreWifiRangingParams *params, 87 const void *cookie); 88 89 /** 90 * Performs an active wifi scan. 91 * 92 * This is currently a 1:1 mapping into the PAL. If more than one nanoapp 93 * requests an active wifi scan, this will be an assertion failure for debug 94 * builds and a no-op in production (ie: subsequent requests are ignored). 95 * 96 * @param nanoapp The nanoapp that has requested an active wifi scan. 97 * @param params Non-null pointer to the scan parameters structure supplied by 98 * the nanoapp. 99 * @param cookie A cookie that is round-tripped back to the nanoapp to provide 100 * a context when making the request. 101 * 102 * @return true if the request was accepted. The result is delivered 103 * asynchronously through a CHRE event. 104 */ 105 bool requestScan(Nanoapp *nanoapp, const chreWifiScanParams *params, 106 const void *cookie); 107 108 /** 109 * Passes the result of an RTT ranging request on to the requesting nanoapp. 110 * 111 * @param errorCode Value from enum chreError 112 * @param event Event containing ranging results, or null if errorCode is not 113 * chreError 114 */ 115 void handleRangingEvent(uint8_t errorCode, 116 struct chreWifiRangingEvent *event); 117 118 /** 119 * Handles the result of a request to PlatformWifi to change the state of the 120 * scan monitor. 121 * 122 * @param enabled true if the result of the operation was an enabled scan 123 * monitor. 124 * @param errorCode an error code that is provided to indicate success or what 125 * type of error has occurred. See the chreError enum in the CHRE API 126 * for additional details. 127 */ 128 void handleScanMonitorStateChange(bool enabled, uint8_t errorCode); 129 130 /** 131 * Handles the result of a request to the PlatformWifi to request an active 132 * Wifi scan. 133 * 134 * @param pending The result of the request was successful and the results 135 * be sent via the handleScanEvent method. 136 * @param errorCode an error code that is used to indicate success or what 137 * type of error has occurred. See the chreError enum in the CHRE API 138 * for additional details. 139 */ 140 void handleScanResponse(bool pending, uint8_t errorCode); 141 142 /** 143 * Handles a CHRE wifi scan event. 144 * 145 * @param event The wifi scan event provided to the wifi request manager. This 146 * memory is guaranteed not to be modified until it has been explicitly 147 * released through the PlatformWifi instance. 148 */ 149 void handleScanEvent(chreWifiScanEvent *event); 150 151 /** 152 * Prints state in a string buffer. Must only be called from the context of 153 * the main CHRE thread. 154 * 155 * @param buffer Pointer to the start of the buffer. 156 * @param bufferPos Pointer to buffer position to start the print (in-out). 157 * @param size Size of the buffer in bytes. 158 */ 159 void logStateToBuffer(char *buffer, size_t *bufferPos, 160 size_t bufferSize) const; 161 162 private: 163 struct PendingRequestBase { 164 uint32_t nanoappInstanceId; //!< ID of the Nanoapp issuing this request 165 const void *cookie; //!< User data supplied by the nanoapp 166 }; 167 168 struct PendingRangingRequest : public PendingRequestBase { 169 //! If the request was queued, a variable-length list of devices to 170 //! perform ranging against (used to reconstruct chreWifiRangingParams) 171 Buffer<struct chreWifiRangingTarget> targetList; 172 }; 173 174 struct PendingScanMonitorRequest : public PendingRequestBase { 175 bool enable; //!< Requested scan monitor state 176 }; 177 178 static constexpr size_t kMaxScanMonitorStateTransitions = 8; 179 static constexpr size_t kMaxPendingRangingRequests = 4; 180 181 PlatformWifi mPlatformWifi; 182 183 //! The queue of state transition requests for the scan monitor. Only one 184 //! asynchronous scan monitor state transition can be in flight at one time. 185 //! Any further requests are queued here. 186 ArrayQueue<PendingScanMonitorRequest, kMaxScanMonitorStateTransitions> 187 mPendingScanMonitorRequests; 188 189 //! The list of nanoapps who have enabled scan monitoring. This list is 190 //! maintained to ensure that nanoapps are always subscribed to wifi scan 191 //! results as requested. Note that a request for wifi scan monitoring can 192 //! exceed the duration of a single active wifi scan request. This makes it 193 //! insuitable only subscribe to wifi scan events when an active request is 194 //! made and the scan monitor must remain enabled when an active request has 195 //! completed. 196 DynamicVector<uint32_t> mScanMonitorNanoapps; 197 198 // TODO: Support multiple requests for active wifi scans. 199 //! The instance ID of the nanoapp that has a pending active scan request. At 200 //! this time, only one nanoapp can have a pending request for an active WiFi 201 //! scan. 202 Optional<uint32_t> mScanRequestingNanoappInstanceId; 203 204 //! The cookie passed in by a nanoapp making an active request for wifi scans. 205 //! Note that this will only be valid if the mScanRequestingNanoappInstanceId 206 //! is set. 207 const void *mScanRequestingNanoappCookie; 208 209 //! This is set to true if the results of an active scan request are pending. 210 bool mScanRequestResultsArePending = false; 211 212 //! Accumulates the number of scan event results to determine when the last 213 //! in a scan event stream has been received. 214 uint8_t mScanEventResultCountAccumulator = 0; 215 216 //! System time when last scan request was made. 217 Nanoseconds mLastScanRequestTime; 218 219 //! Tracks the in-flight ranging request and any others queued up behind it 220 ArrayQueue<PendingRangingRequest, kMaxPendingRangingRequests> 221 mPendingRangingRequests; 222 223 //! Helps ensure we don't get stuck if platform isn't behaving as expected 224 Nanoseconds mRangingResponseTimeout; 225 226 /** 227 * @return true if the scan monitor is enabled by any nanoapps. 228 */ 229 bool scanMonitorIsEnabled() const; 230 231 /** 232 * @param instanceId the instance ID of the nanoapp. 233 * @param index an optional pointer to a size_t to populate with the index of 234 * the nanoapp in the list of nanoapps. 235 * 236 * @return true if the nanoapp has an active request for scan monitoring. 237 */ 238 bool nanoappHasScanMonitorRequest(uint32_t instanceId, 239 size_t *index = nullptr) const; 240 241 /** 242 * @param requestedState The requested state to compare against. 243 * @param nanoappHasRequest The requesting nanoapp has an existing request. 244 * 245 * @return true if the scan monitor is in the requested state. 246 */ 247 bool scanMonitorIsInRequestedState(bool requestedState, 248 bool nanoappHasRequest) const; 249 250 /** 251 * @param requestedState The requested state to compare against. 252 * @param nanoappHasRequest The requesting nanoapp has an existing request. 253 * 254 * @return true if a state transition is required to reach the requested 255 * state. 256 */ 257 bool scanMonitorStateTransitionIsRequired(bool requestedState, 258 bool nanoappHasRequest) const; 259 260 /** 261 * Builds a scan monitor state transition and adds it to the queue of incoming 262 * requests. 263 * @param nanoapp A non-null pointer to a nanoapp that is requesting the 264 * change. 265 * @param enable The target requested scan monitoring state. 266 * @param cookie The pointer cookie passed in by the calling nanoapp to return 267 * to the nanoapp when the request completes. 268 * 269 * @return true if the request is enqueued or false if the queue is full. 270 */ 271 bool addScanMonitorRequestToQueue(Nanoapp *nanoapp, bool enable, 272 const void *cookie); 273 274 /** 275 * Adds a nanoapp to the list of nanoapps that are monitoring for wifi scans. 276 * @param enable true if enabling scan monitoring. 277 * @param instanceId The instance ID of the scan monitoring nanoapp. 278 * 279 * @return true if the nanoapp was added to the list. 280 */ 281 bool updateNanoappScanMonitoringList(bool enable, uint32_t instanceId); 282 283 /** 284 * Posts an event to a nanoapp indicating the result of a wifi scan monitoring 285 * configuration change. 286 * 287 * @param nanoappInstanceId The nanoapp instance ID to direct the event to. 288 * @param success If the request for a wifi resource was successful. 289 * @param enable The target state of the request. If enable is set to false 290 * and the request was successful, the nanoapp is removed from the 291 * list of nanoapps requesting scan monitoring. 292 * @param errorCode The error code when success is set to false. 293 * @param cookie The cookie to be provided to the nanoapp. This is 294 * round-tripped from the nanoapp to provide context. 295 * 296 * @return true if the event was successfully posted to the event loop. 297 */ 298 bool postScanMonitorAsyncResultEvent( 299 uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode, 300 const void *cookie); 301 302 /** 303 * Calls through to postScanMonitorAsyncResultEvent but invokes the 304 * FATAL_ERROR macro if the event is not posted successfully. This is used in 305 * asynchronous contexts where a nanoapp could be stuck waiting for a response 306 * but CHRE failed to enqueue one. For parameter details, 307 * @see postScanMonitorAsyncResultEvent 308 */ 309 void postScanMonitorAsyncResultEventFatal( 310 uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode, 311 const void *cookie); 312 313 /** 314 * Posts an event to a nanoapp indicating the result of a request for an 315 * active wifi scan. 316 * 317 * @param nanoappInstanceId The nanoapp instance ID to direct the event to. 318 * @param success If the request for a wifi resource was successful. 319 * @param errorCode The error code when success is set to false. 320 * @param cookie The cookie to be provided to the nanoapp. This is 321 * round-tripped from the nanoapp to provide context. 322 * 323 * @return true if the event was successfully posted to the event loop. 324 */ 325 bool postScanRequestAsyncResultEvent( 326 uint32_t nanoappInstanceId, bool success, uint8_t errorCode, 327 const void *cookie); 328 329 /** 330 * Calls through to postScanRequestAsyncResultEvent but invokes the 331 * FATAL_ERROR macro if the event is not posted successfully. This is used in 332 * asynchronous contexts where a nanoapp could be stuck waiting for a response 333 * but CHRE failed to enqueue one. For parameter details, 334 * @see postScanRequestAsyncResultEvent 335 */ 336 void postScanRequestAsyncResultEventFatal( 337 uint32_t nanoappInstanceId, bool success, uint8_t errorCode, 338 const void *cookie); 339 340 /** 341 * Posts a broadcast event containing the results of a wifi scan. Failure to 342 * post this event is a FATAL_ERROR. This is unrecoverable as the nanoapp will 343 * be stuck waiting for wifi scan results but there may be a gap. 344 * 345 * @param event the wifi scan event. 346 */ 347 void postScanEventFatal(chreWifiScanEvent *event); 348 349 /** 350 * Handles the result of a request to PlatformWifi to change the state of the 351 * scan monitor. See the handleScanMonitorStateChange method which may be 352 * called from any thread. This method is intended to be invoked on the CHRE 353 * event loop thread. 354 * 355 * @param enabled true if the result of the operation was an enabled scan 356 * monitor. 357 * @param errorCode an error code that is provided to indicate success or what 358 * type of error has occurred. See the chreError enum in the CHRE API 359 * for additional details. 360 */ 361 void handleScanMonitorStateChangeSync(bool enabled, uint8_t errorCode); 362 363 /** 364 * Handles the result of a request to PlatformWifi to perform an active WiFi 365 * scan. See the handleScanResponse method which may be called from any 366 * thread. This method is intended to be invoked on the CHRE event loop 367 * thread. 368 * 369 * @param enabled true if the result of the operation was an enabled scan 370 * monitor. 371 * @param errorCode an error code that is provided to indicate success or what 372 * type of error has occurred. See the chreError enum in the CHRE API 373 * for additional details. 374 */ 375 void handleScanResponseSync(bool pending, uint8_t errorCode); 376 377 /** 378 * Sends CHRE_EVENT_WIFI_ASYNC_RESULT for the ranging request at the head of 379 * the pending queue. 380 * 381 * @param errorCode Indicates the overall result of the ranging operation 382 * 383 * @return true on success 384 */ 385 bool postRangingAsyncResult(uint8_t errorCode); 386 387 /** 388 * Issues the next pending ranging request to the platform. 389 * 390 * @return Result of PlatformWifi::requestRanging() 391 */ 392 bool dispatchQueuedRangingRequest(); 393 394 /** 395 * Processes the result of a ranging request within the context of the CHRE 396 * thread. 397 * 398 * @param errorCode Result of the ranging operation 399 * @param event On success, pointer to event data provided by platform 400 */ 401 void handleRangingEventSync(uint8_t errorCode, 402 struct chreWifiRangingEvent *event); 403 404 /** 405 * Handles the releasing of a WiFi scan event and unsubscribes a nanoapp who 406 * has made an active request for a wifi scan from WiFi scan events in the 407 * future (if it has not subscribed to passive events). 408 * 409 * @param scanEvent The scan event to release. 410 */ 411 void handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent); 412 413 /** 414 * Releases a wifi scan event after nanoapps have consumed it. 415 * 416 * @param eventType the type of event being freed. 417 * @param eventData a pointer to the scan event to release. 418 */ 419 static void freeWifiScanEventCallback(uint16_t eventType, void *eventData); 420 static void freeWifiRangingEventCallback(uint16_t eventType, void *eventData); 421 }; 422 423 } // namespace chre 424 425 #endif // CHRE_CORE_WIFI_REQUEST_MANAGER_H_ 426