Home | History | Annotate | Download | only in core
      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 #include "chre/util/time.h"
     24 #include "chre_api/chre/wifi.h"
     25 
     26 namespace chre {
     27 
     28 /**
     29  * The WifiRequestManager handles requests from nanoapps for Wifi information.
     30  * This includes multiplexing multiple requests into one for the platform to
     31  * handle.
     32  *
     33  * This class is effectively a singleton as there can only be one instance of
     34  * the PlatformWifi instance.
     35  */
     36 class WifiRequestManager : public NonCopyable {
     37  public:
     38    /**
     39     * Initializes the WifiRequestManager with a default state and memory for any
     40     * requests.
     41     */
     42   WifiRequestManager();
     43 
     44   /**
     45    * Initializes the underlying platform-specific WiFi module. Must be called
     46    * prior to invoking any other methods in this class.
     47    */
     48   void init();
     49 
     50   /**
     51    * @return the WiFi capabilities exposed by this platform.
     52    */
     53   uint32_t getCapabilities();
     54 
     55   /**
     56    * Handles a request from a nanoapp to configure the scan monitor. This
     57    * includes merging multiple requests for scan monitoring to the PAL (ie: if
     58    * multiple apps enable the scan monitor the PAL is only enabled once).
     59    *
     60    * @param nanoapp The nanoapp that has requested that the scan monitor be
     61    *        configured.
     62    * @param enable true to enable scan monitoring, false to disable scan
     63    *        monitoring.
     64    * @param cookie A cookie that is round-tripped back to the nanoapp to
     65    *        provide a context when making the request.
     66    *
     67    * @return true if the request was accepted. The result is delivered
     68    *         asynchronously through a CHRE event.
     69    */
     70   bool configureScanMonitor(Nanoapp *nanoapp, bool enable, const void *cookie);
     71 
     72   /**
     73    * Handles a nanoapp's request for RTT ranging against a set of devices.
     74    *
     75    * @param nanoapp Nanoapp issuing the request.
     76    * @param params Non-null pointer to parameters, supplied by the nanoapp via
     77    *        chreWifiRequestRangingAsync()
     78    * @param cookie Opaque pointer supplied by the nanoapp and passed back in the
     79    *        async result.
     80    *
     81    * @return true if the request was accepted. The result is delivered
     82    *         asynchronously through a CHRE event.
     83    */
     84   bool requestRanging(Nanoapp *nanoapp, const chreWifiRangingParams *params,
     85                       const void *cookie);
     86 
     87   /**
     88    * Performs an active wifi scan.
     89    *
     90    * This is currently a 1:1 mapping into the PAL. If more than one nanoapp
     91    * requests an active wifi scan, this will be an assertion failure for debug
     92    * builds and a no-op in production (ie: subsequent requests are ignored).
     93    *
     94    * @param nanoapp The nanoapp that has requested an active wifi scan.
     95    * @param params Non-null pointer to the scan parameters structure supplied by
     96    *        the nanoapp.
     97    * @param cookie A cookie that is round-tripped back to the nanoapp to provide
     98    *        a context when making the request.
     99    *
    100    * @return true if the request was accepted. The result is delivered
    101    *         asynchronously through a CHRE event.
    102    */
    103   bool requestScan(Nanoapp *nanoapp, const chreWifiScanParams *params,
    104                    const void *cookie);
    105 
    106   /**
    107    * Passes the result of an RTT ranging request on to the requesting nanoapp.
    108    *
    109    * @param errorCode Value from enum chreError
    110    * @param event Event containing ranging results, or null if errorCode is not
    111    *        chreError
    112    */
    113   void handleRangingEvent(uint8_t errorCode,
    114                           struct chreWifiRangingEvent *event);
    115 
    116   /**
    117    * Handles the result of a request to PlatformWifi to change the state of the
    118    * scan monitor.
    119    *
    120    * @param enabled true if the result of the operation was an enabled scan
    121    *        monitor.
    122    * @param errorCode an error code that is provided to indicate success or what
    123    *        type of error has occurred. See the chreError enum in the CHRE API
    124    *        for additional details.
    125    */
    126   void handleScanMonitorStateChange(bool enabled, uint8_t errorCode);
    127 
    128   /**
    129    * Handles the result of a request to the PlatformWifi to request an active
    130    * Wifi scan.
    131    *
    132    * @param pending The result of the request was successful and the results
    133    *        be sent via the handleScanEvent method.
    134    * @param errorCode an error code that is used to indicate success or what
    135    *        type of error has occurred. See the chreError enum in the CHRE API
    136    *        for additional details.
    137    */
    138   void handleScanResponse(bool pending, uint8_t errorCode);
    139 
    140   /**
    141    * Handles a CHRE wifi scan event.
    142    *
    143    * @param event The wifi scan event provided to the wifi request manager. This
    144    *        memory is guaranteed not to be modified until it has been explicitly
    145    *        released through the PlatformWifi instance.
    146    */
    147   void handleScanEvent(chreWifiScanEvent *event);
    148 
    149   /**
    150    * Prints state in a string buffer. Must only be called from the context of
    151    * the main CHRE thread.
    152    *
    153    * @param buffer Pointer to the start of the buffer.
    154    * @param bufferPos Pointer to buffer position to start the print (in-out).
    155    * @param size Size of the buffer in bytes.
    156    *
    157    * @return true if entire log printed, false if overflow or error.
    158    */
    159   bool 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     DynamicVector<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