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 void 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 a change to the session state is required given a set of 211 * parameters. 212 * 213 * @param requestedState The target state requested by a nanoapp. 214 * @param minInterval The minimum reporting interval. 215 * @param nanoappHasRequest If the nanoapp already has a request. 216 * @param requestIndex The index of the request in the list of open requests 217 * if nanoappHasRequest is set to true. 218 * 219 * @return true if a state transition is required. 220 */ 221 bool stateTransitionIsRequired( 222 bool requestedState, Milliseconds minInterval, bool nanoappHasRequest, 223 size_t requestIndex) const; 224 225 /** 226 * Updates the session requests given a nanoapp and the interval requested. 227 * 228 * @param enable true if enabling the session. 229 * @param minInterval the minimum reporting interval if enable is true. 230 * @param instanceId the nanoapp instance ID that owns the request. 231 * 232 * @return true if the session request list was updated. 233 */ 234 bool updateRequests(bool enable, Milliseconds minInterval, 235 uint32_t instanceId); 236 237 /** 238 * Posts the result of a GNSS session add/remove request. 239 * 240 * @param instanceId The nanoapp instance ID that made the request. 241 * @param success true if the operation was successful. 242 * @param enable true if enabling the session. 243 * @param minInterval the minimum reporting interval. 244 * @param errorCode the error code as a result of this operation. 245 * @param cookie the cookie that the nanoapp is provided for context. 246 * 247 * @return true if the event was successfully posted. 248 */ 249 bool postAsyncResultEvent( 250 uint32_t instanceId, bool success, bool enable, 251 Milliseconds minInterval, uint8_t errorCode, const void *cookie); 252 253 /** 254 * Calls through to postAsyncResultEvent but invokes FATAL_ERROR if the 255 * event is not posted successfully. This is used in asynchronous contexts 256 * where a nanoapp could be stuck waiting for a response but CHRE failed to 257 * enqueue one. For parameter details, 258 * @see postAsyncResultEvent 259 */ 260 void postAsyncResultEventFatal( 261 uint32_t instanceId, bool success, bool enable, 262 Milliseconds minInterval, uint8_t errorCode, const void *cookie); 263 264 /** 265 * Handles the result of a request to PlatformGnss to change the state of 266 * the session. See the handleStatusChange method which may be called from 267 * any thread. This method is intended to be invoked on the CHRE event loop 268 * thread. 269 * 270 * @param enabled true if the session was enabled 271 * @param errorCode an error code that is provided to indicate success. 272 */ 273 void handleStatusChangeSync(bool enabled, uint8_t errorCode); 274 275 /** 276 * Releases a GNSS report event after nanoapps have consumed it. 277 * 278 * @param eventType the type of event being freed. 279 * @param eventData a pointer to the scan event to release. 280 */ 281 static void freeReportEventCallback(uint16_t eventType, void *eventData); 282 283 /** 284 * Configures PlatformGnss based on session settings. 285 * 286 * @return true if PlatformGnss has accepted the setting. 287 */ 288 bool controlPlatform(bool enable, Milliseconds minInterval, 289 Milliseconds minTimeToNext); 290 }; 291 292 /** 293 * The GnssManager handles platform init, capability query, and delagates debug 294 * dump and all GNSS request management to GnssSession(s), which includes 295 * multiplexing multiple requests into one for the platform to handle. 296 * 297 * This class is effectively a singleton as there can only be one instance of 298 * the PlatformGnss instance. 299 */ 300 class GnssManager : public NonCopyable { 301 public: 302 /** 303 * Constructs a GnssManager. 304 */ 305 GnssManager(); 306 307 /** 308 * Initializes the underlying platform-specific GNSS module. Must be called 309 * prior to invoking any other methods in this class. 310 */ 311 void init(); 312 313 /** 314 * @return the GNSS capabilities exposed by this platform. 315 */ 316 uint32_t getCapabilities(); 317 getLocationSession()318 GnssSession& getLocationSession() { 319 return mLocationSession; 320 }; 321 getMeasurementSession()322 GnssSession& getMeasurementSession() { 323 return mMeasurementSession; 324 }; 325 326 /** 327 * Prints state in a string buffer. Must only be called from the context of 328 * the main CHRE thread. 329 * 330 * @param buffer Pointer to the start of the buffer. 331 * @param bufferPos Pointer to buffer position to start the print (in-out). 332 * @param size Size of the buffer in bytes. 333 * 334 * @return true if entire log printed, false if overflow or error. 335 */ 336 void logStateToBuffer(char *buffer, size_t *bufferPos, 337 size_t bufferSize) const; 338 339 private: 340 // Allows GnssSession to access mPlatformGnss. 341 friend class GnssSession; 342 343 //! The platform GNSS interface. 344 PlatformGnss mPlatformGnss; 345 346 //! The instance of location session. 347 GnssSession mLocationSession; 348 349 //! The instance of measurement session. 350 GnssSession mMeasurementSession; 351 }; 352 353 } // namespace chre 354 355 #endif // CHRE_CORE_GNSS_MANAGER_H_ 356