Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2018 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_GNSS_MANAGER_H_
     18 #define CHRE_CORE_GNSS_MANAGER_H_
     19 
     20 #include <cstdint>
     21 
     22 #include "chre/core/nanoapp.h"
     23 #include "chre/platform/platform_gnss.h"
     24 #include "chre/util/non_copyable.h"
     25 #include "chre/util/time.h"
     26 
     27 namespace chre {
     28 
     29 class GnssManager;
     30 
     31 /**
     32  * A helper class that manages requests for a GNSS location or measurement
     33  * session.
     34  */
     35 class GnssSession {
     36  public:
     37   /**
     38    * Adds a request to a session asynchronously. The result is delivered
     39    * through a CHRE_EVENT_GNSS_ASYNC_RESULT event.
     40    *
     41    * @param nanoapp The nanoapp adding the request.
     42    * @param minInterval The minimum reporting interval for results.
     43    * @param timeToNext The amount of time that the GNSS system is allowed to
     44    *        delay generating a report.
     45    * @param cookie A cookie that is round-tripped to provide context to the
     46    *        nanoapp making the request.
     47    *
     48    * @return true if the request was accepted for processing.
     49    */
     50   bool addRequest(Nanoapp *nanoapp, Milliseconds minInterval,
     51                   Milliseconds minTimeToNext, const void *cookie);
     52 
     53   /**
     54    * Removes a request from a session asynchronously. The result is delivered
     55    * through a CHRE_EVENT_GNSS_ASYNC_RESULT event.
     56    *
     57    * @param nanoapp The nanoapp removing the request.
     58    * @param cookie A cookie that is round-tripped to provide context to the
     59    *        nanoapp making the request.
     60    *
     61    * @return true if the request was accepted for processing.
     62    */
     63   bool removeRequest(Nanoapp *nanoapp, const void *cookie);
     64 
     65   /**
     66    * Handles the result of a request to the PlatformGnss to request a change to
     67    * the session.
     68    *
     69    * @param enabled true if the session is currently active.
     70    * @param errorCode an error code that is used to indicate success or what
     71    *        type of error has occured. See chreError enum in the CHRE API for
     72    *        additional details.
     73    */
     74   void handleStatusChange(bool enabled, uint8_t errorCode);
     75 
     76   /**
     77    * Handles a CHRE GNSS report (location/data) event.
     78    *
     79    * @param event The GNSS report event provided to the GNSS session. This
     80    *        memory is guaranteed not to be modified until it has been explicitly
     81    *        released through the PlatformGnss instance.
     82    */
     83   void handleReportEvent(void *event);
     84 
     85   /**
     86    * Prints state in a string buffer. Must only be called from the context of
     87    * the main CHRE thread.
     88    *
     89    * @see GnssManager::logStateToBuffer
     90    */
     91   bool logStateToBuffer(char *buffer, size_t *bufferPos, size_t bufferSize)
     92       const;
     93 
     94  private:
     95   /**
     96    * Tracks a nanoapp that has subscribed to a session and the reporting
     97    * interval.
     98    */
     99   struct Request {
    100     //! The nanoapp instance ID that made this request.
    101     uint32_t nanoappInstanceId;
    102 
    103     //! The interval of results requested.
    104     Milliseconds minInterval;
    105   };
    106 
    107   /**
    108    * Tracks the state of the GNSS engine.
    109    */
    110   struct StateTransition {
    111     //! The nanoapp instance ID that prompted the change.
    112     uint32_t nanoappInstanceId;
    113 
    114     //! The cookie provided to the CHRE API when the nanoapp requested a
    115     //! change to the state of the GNSS engine.
    116     const void *cookie;
    117 
    118     //! The target state of the GNSS engine.
    119     bool enable;
    120 
    121     //! The target minimum reporting interval for the GNSS engine. This is only
    122     //! valid if enable is set to true.
    123     Milliseconds minInterval;
    124   };
    125 
    126   //! The event type of the session's report data.
    127   uint16_t mReportEventType;
    128 
    129   //! The request type to start and stop a session.
    130   uint8_t mStartRequestType;
    131   uint8_t mStopRequestType;
    132 
    133   //! The session name, used in logging state.
    134   const char *mName;
    135 
    136   //! The maximum number of pending state transitions allowed.
    137   static constexpr size_t kMaxGnssStateTransitions = 8;
    138 
    139   //! The queue of state transitions for the GNSS engine. Only one asynchronous
    140   //! state transition can be in flight at one time. Any further requests are
    141   //! queued here.
    142   ArrayQueue<StateTransition, kMaxGnssStateTransitions> mStateTransitions;
    143 
    144   //! The request multiplexer for GNSS session requests.
    145   DynamicVector<Request> mRequests;
    146 
    147   //! The current report interval being sent to the session. This is only valid
    148   //! if the mRequests is non-empty.
    149   Milliseconds mCurrentInterval = Milliseconds(UINT64_MAX);
    150 
    151   // Allows GnssManager to access constructor.
    152   friend class GnssManager;
    153 
    154   /**
    155    * Constructs a GnssSesson.
    156    *
    157    * @param reportEventType The report event type of this GNSS session.
    158    *        Currently, only CHRE_EVENT_GNSS_LOCATION for a location session and
    159    *        CHRE_EVENT_GNSS_LOCATION for a measurement session are supported.
    160    */
    161   GnssSession(uint16_t reportEventType);
    162 
    163   /**
    164    * Configures the GNSS engine to be enabled/disabled. If enable is set to true
    165    * then the minInterval and minTimeToNext values are valid.
    166    *
    167    * @param nanoapp The nanoapp requesting the state change for the engine.
    168    * @param enable Whether to enable or disable the engine.
    169    * @param minInterval The minimum reporting interval requested by the nanoapp.
    170    * @param minTimeToNext The minimum time to the next report.
    171    * @param cookie The cookie provided by the nanoapp to round-trip for context.
    172    *
    173    * @return true if the request was accepted.
    174    */
    175   bool configure(Nanoapp *nanoapp, bool enable, Milliseconds minInterval,
    176                  Milliseconds minTimeToNext, const void *cookie);
    177 
    178   /**
    179    * Checks if a nanoapp has an open session request.
    180    *
    181    * @param instanceId The nanoapp instance ID to search for.
    182    * @param requestIndex A pointer to an index to populate if the nanoapp has an
    183    *        open session request.
    184    *
    185    * @return true if the provided instanceId was found.
    186    */
    187   bool nanoappHasRequest(uint32_t instanceId, size_t *requestIndex = nullptr)
    188       const;
    189 
    190   /**
    191    * Adds a request for a session to the queue of state transitions.
    192    *
    193    * @param instanceId The nanoapp instance ID requesting a session.
    194    * @param enable Whether the session is being enabled or disabled for this
    195    *        nanoapp.
    196    * @param minInterval The minimum interval requested by the nanoapp.
    197    * @param cookie A cookie that is round-tripped to the nanoapp for context.
    198    *
    199    * @return true if the state transition was added to the queue.
    200    */
    201   bool addRequestToQueue(uint32_t instanceId, bool enable,
    202                          Milliseconds minInterval, const void *cookie);
    203 
    204   /**
    205    * @return true if the session is currently enabled.
    206    */
    207   bool isEnabled() const;
    208 
    209   /**
    210    * Determines if the session is already in the requested state.
    211    *
    212    * @param requestedState The target state of the session.
    213    * @param minInterval The reporting interval if requestedState is true.
    214    * @param nanoappHasRequest true if the requesting nanoapp already has an
    215    *        outstanding request.
    216    *
    217    * @return true if the session is already in the requested state.
    218    */
    219   bool isInRequestedState(bool requestedState, Milliseconds minInterval,
    220                           bool nanoappHasRequest) const;
    221 
    222   /**
    223    * Determines if a change to the session state is required given a set of
    224    * parameters.
    225    *
    226    * @param requestedState The target state requested by a nanoapp.
    227    * @param minInterval The minimum reporting interval.
    228    * @param nanoappHasRequest If the nanoapp already has a request.
    229    * @param requestIndex The index of the request in the list of open requests
    230    *        if nanoappHasRequest is set to true.
    231    *
    232    * @return true if a state transition is required.
    233    */
    234   bool stateTransitionIsRequired(
    235       bool requestedState, Milliseconds minInterval, bool nanoappHasRequest,
    236       size_t requestIndex) const;
    237 
    238   /**
    239    * Updates the session requests given a nanoapp and the interval requested.
    240    *
    241    * @param enable true if enabling the session.
    242    * @param minInterval the minimum reporting interval if enable is true.
    243    * @param instanceId the nanoapp instance ID that owns the request.
    244    *
    245    * @return true if the session request list was updated.
    246    */
    247   bool updateRequests(bool enable, Milliseconds minInterval,
    248                       uint32_t instanceId);
    249 
    250   /**
    251    * Posts the result of a GNSS session add/remove request.
    252    *
    253    * @param instanceId The nanoapp instance ID that made the request.
    254    * @param success true if the operation was successful.
    255    * @param enable true if enabling the session.
    256    * @param minInterval the minimum reporting interval.
    257    * @param errorCode the error code as a result of this operation.
    258    * @param cookie the cookie that the nanoapp is provided for context.
    259    *
    260    * @return true if the event was successfully posted.
    261    */
    262   bool postAsyncResultEvent(
    263       uint32_t instanceId, bool success, bool enable,
    264       Milliseconds minInterval, uint8_t errorCode, const void *cookie);
    265 
    266   /**
    267    * Calls through to postAsyncResultEvent but invokes FATAL_ERROR if the
    268    * event is not posted successfully. This is used in asynchronous contexts
    269    * where a nanoapp could be stuck waiting for a response but CHRE failed to
    270    * enqueue one. For parameter details,
    271    * @see postAsyncResultEvent
    272    */
    273   void postAsyncResultEventFatal(
    274       uint32_t instanceId, bool success, bool enable,
    275       Milliseconds minInterval, uint8_t errorCode, const void *cookie);
    276 
    277   /**
    278    * Handles the result of a request to PlatformGnss to change the state of
    279    * the session. See the handleStatusChange method which may be called from
    280    * any thread. This method is intended to be invoked on the CHRE event loop
    281    * thread.
    282    *
    283    * @param enabled true if the session was enabled
    284    * @param errorCode an error code that is provided to indicate success.
    285    */
    286   void handleStatusChangeSync(bool enabled, uint8_t errorCode);
    287 
    288   /**
    289    * Releases a GNSS report event after nanoapps have consumed it.
    290    *
    291    * @param eventType the type of event being freed.
    292    * @param eventData a pointer to the scan event to release.
    293    */
    294   static void freeReportEventCallback(uint16_t eventType, void *eventData);
    295 
    296   /**
    297    * Configures PlatformGnss based on session settings.
    298    *
    299    * @return true if PlatformGnss has accepted the setting.
    300    */
    301   bool controlPlatform(bool enable, Milliseconds minInterval,
    302                        Milliseconds minTimeToNext);
    303 };
    304 
    305 /**
    306  * The GnssManager handles platform init, capability query, and delagates debug
    307  * dump and all GNSS request management to GnssSession(s), which includes
    308  * multiplexing multiple requests into one for the platform to handle.
    309  *
    310  * This class is effectively a singleton as there can only be one instance of
    311  * the PlatformGnss instance.
    312  */
    313 class GnssManager : public NonCopyable {
    314  public:
    315   /**
    316    * Constructs a GnssManager.
    317    */
    318   GnssManager();
    319 
    320   /**
    321    * Initializes the underlying platform-specific GNSS module. Must be called
    322    * prior to invoking any other methods in this class.
    323    */
    324   void init();
    325 
    326   /**
    327    * @return the GNSS capabilities exposed by this platform.
    328    */
    329   uint32_t getCapabilities();
    330 
    331   GnssSession& getLocationSession() {
    332     return mLocationSession;
    333   };
    334 
    335   GnssSession& getMeasurementSession() {
    336     return mMeasurementSession;
    337   };
    338 
    339   /**
    340    * Prints state in a string buffer. Must only be called from the context of
    341    * the main CHRE thread.
    342    *
    343    * @param buffer Pointer to the start of the buffer.
    344    * @param bufferPos Pointer to buffer position to start the print (in-out).
    345    * @param size Size of the buffer in bytes.
    346    *
    347    * @return true if entire log printed, false if overflow or error.
    348    */
    349   bool logStateToBuffer(char *buffer, size_t *bufferPos,
    350                         size_t bufferSize) const;
    351 
    352  private:
    353   // Allows GnssSession to access mPlatformGnss.
    354   friend class GnssSession;
    355 
    356   //! The platform GNSS interface.
    357   PlatformGnss mPlatformGnss;
    358 
    359   //! The instance of location session.
    360   GnssSession mLocationSession;
    361 
    362   //! The instance of measurement session.
    363   GnssSession mMeasurementSession;
    364 };
    365 
    366 }  // namespace chre
    367 
    368 #endif  // CHRE_CORE_GNSS_MANAGER_H_
    369