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 getLocationSession()331 GnssSession& getLocationSession() { 332 return mLocationSession; 333 }; 334 getMeasurementSession()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