1 /* 2 * Copyright (C) 2017 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_REQUEST_MANAGER_H_ 18 #define CHRE_CORE_GNSS_REQUEST_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 /** 30 * The GnssRequestManager handles requests from nanoapps for GNSS data. This 31 * includes multiplexing multiple requests into one for the platform to handle. 32 * 33 * This class is effectively a singleton as there can only be one instance of 34 * the PlatformGnss instance. 35 */ 36 class GnssRequestManager : public NonCopyable { 37 public: 38 /** 39 * Initializes a GnssRequestManager. 40 */ 41 GnssRequestManager(); 42 43 /** 44 * Initializes the underlying platform-specific GNSS module. Must be called 45 * prior to invoking any other methods in this class. 46 */ 47 void init(); 48 49 /** 50 * @return the GNSS capabilities exposed by this platform. 51 */ 52 uint32_t getCapabilities(); 53 54 /** 55 * Starts a location session asynchronously. The result is delivered through 56 * a CHRE_EVENT_GNSS_ASYNC_RESULT event. 57 * 58 * @param nanoapp The nanoapp requesting the location session. 59 * @param minInterval The minimum reporting interval for location results. 60 * @param timeToNextFix The amount of time that the locationing system is 61 * allowed to delay generating a fix. 62 * @param cookie A cookie that is round-tripped to provide context to the 63 * nanoapp making the request. 64 * @return true if the request was accepted for processing. 65 */ 66 bool startLocationSession(Nanoapp *nanoapp, Milliseconds minInterval, 67 Milliseconds minTimeToNextFix, const void *cookie); 68 69 /** 70 * Stops a location session asynchronously. The result is delivered through a 71 * CHRE_EVENT_GNSS_ASYNC_RESULT event. 72 * 73 * @param nanoapp The nanoapp requesting the location session to stop. 74 * @param cookie A cookie that is round-tripped to provide context to the 75 * nanoapp making the request. 76 * @return true if the request was accepted for processing. 77 */ 78 bool stopLocationSession(Nanoapp *nanoapp, const void *cookie); 79 80 /** 81 * Handles the result of a request to the PlatformGnss to request a change to 82 * the location session. 83 * 84 * @param enabled true if the location session is currently active 85 * @param errorCode an error code that is used to indicate success or what 86 * type of error has occured. See chreError enum in the CHRE API for 87 * additional details. 88 */ 89 void handleLocationSessionStatusChange(bool enabled, uint8_t errorCode); 90 91 /** 92 * Handles a CHRE GNSS location event. 93 * 94 * @param event The GNSS location event provided to the GNSS request manager. 95 * This memory is guaranteed not to be modified until it has been 96 * explicitly released through the PlatformGnss instance. 97 */ 98 void handleLocationEvent(chreGnssLocationEvent *event); 99 100 /** 101 * Prints state in a string buffer. Must only be called from the context of 102 * the main CHRE thread. 103 * 104 * @param buffer Pointer to the start of the buffer. 105 * @param bufferPos Pointer to buffer position to start the print (in-out). 106 * @param size Size of the buffer in bytes. 107 * 108 * @return true if entire log printed, false if overflow or error. 109 */ 110 bool logStateToBuffer(char *buffer, size_t *bufferPos, 111 size_t bufferSize) const; 112 113 private: 114 /** 115 * Tracks a nanoapp that has subscribed to a location session and the 116 * reporting interval. 117 */ 118 struct LocationSessionRequest { 119 //! The nanoapp instance ID that made this request. 120 uint32_t nanoappInstanceId; 121 122 //! The interval of location results requested. 123 Milliseconds minInterval; 124 }; 125 126 /** 127 * Tracks the state of the locationing engine. 128 */ 129 struct LocationSessionStateTransition { 130 //! The nanoapp instance ID that prompted the change. 131 uint32_t nanoappInstanceId; 132 133 //! The cookie provided to the CHRE API when the nanoapp requested a change 134 //! to the state of the location engine. 135 const void *cookie; 136 137 //! The target state of the location engine. 138 bool enable; 139 140 //! The target minimum reporting interval for the location engine. This is 141 //! only valid if enable is set to true. 142 Milliseconds minInterval; 143 }; 144 145 //! The maximum number of state transitions allowed for location and GNSS 146 //! measurement resources. 147 static constexpr size_t kMaxGnssStateTransitions = 8; 148 149 //! The instance of the platform GNSS interface. 150 PlatformGnss mPlatformGnss; 151 152 //! The queue of state transitions for the location engine. Only one 153 //! asynchronous location engine state transition can be in flight at one 154 //! time. Any further requests are queued here. 155 ArrayQueue<LocationSessionStateTransition, 156 kMaxGnssStateTransitions> mLocationSessionStateTransitions; 157 158 //! The request multiplexer for GNSS location requests. 159 DynamicVector<LocationSessionRequest> mLocationSessionRequests; 160 161 //! The current interval being sent to the location session. This is only 162 //! valid if the mLocationSessionRequests is non-empty. 163 Milliseconds mCurrentLocationSessionInterval; 164 165 /** 166 * Configures the location engine to be enabled/disabled. If enable is set to 167 * true then the minInterval and minTimeToFirstFix values are valid. 168 * 169 * @param nanoapp The nanoapp requesting the state change for the location 170 * engine. 171 * @param enable Whether to enable or disable the location engine. 172 * @param minInterval The minimum location reporting interval requested by the 173 * nanoapp. 174 * @param minTimeToFirstFix The minimum time to the first fix. 175 * @param cookie The cookie provided by the nanoapp to round-trip for context. 176 * @return true if the request was accepted. 177 */ 178 bool configureLocationSession(Nanoapp *nanoapp, bool enable, 179 Milliseconds minInterval, 180 Milliseconds minTimeToFirstFix, 181 const void *cookie); 182 183 /** 184 * Checks if a nanoapp has an open location session request. 185 * 186 * @param instanceId The nanoapp instance ID to search for. 187 * @param requestIndex A pointer to an index to populate if the nanoapp has an 188 * open location session. 189 * @return true if the provided instanceId was found. 190 */ 191 bool nanoappHasLocationSessionRequest(uint32_t instanceId, 192 size_t *requestIndex = nullptr); 193 194 /** 195 * Adds a request for a location session to the queue of state transitions. 196 * 197 * @param instanceId The nanoapp instance ID requesting a location session. 198 * @param enable Whether the location session is being enabled or disabled for 199 * this nanoapp. 200 * @param minInterval The minimum interval reqested by the nanoapp. 201 * @param cookie A cookie that is round-tripped to the nanoapp for context. 202 * @return true if the state transition was added to the queue. 203 */ 204 bool addLocationSessionRequestToQueue(uint32_t instanceId, bool enable, 205 Milliseconds minInterval, 206 const void *cookie); 207 208 /** 209 * @return true if the location session is currently enabled. 210 */ 211 bool locationSessionIsEnabled(); 212 213 /** 214 * Determines if the location session is already in the requested state. 215 * 216 * @param requestedState The target state of the location session. 217 * @param minInterval The reporting interval if the requestedState is true. 218 * @param nanoappHasRequest true if the requesting nanoapp already has an 219 * outstanding request. 220 * @return true if the location session is already in the requested state. 221 */ 222 bool locationSessionIsInRequestedState(bool requestedState, 223 Milliseconds minInterval, 224 bool nanoappHasRequest); 225 226 /** 227 * Determines if a change to the location session state is required given a 228 * set of parameters. 229 * 230 * @param requestedState The target state requested by a nanoapp. 231 * @param minInterval The minimum location reporting interval. 232 * @param nanoappHasRequest If the nanoapp already has a request. 233 * @param requestIndex The index of the request in the list of open requests 234 * if nanoappHasRequest is set to true. 235 * @return true if a state transition is required. 236 */ 237 bool locationSessionStateTransitionIsRequired(bool requestedState, 238 Milliseconds minInterval, 239 bool nanoappHasRequest, 240 size_t requestIndex); 241 242 /** 243 * Updates the location session requests given a nanoapp and the interval 244 * requested. 245 * 246 * @param enable true if enabling the location session. 247 * @param minInterval the minimum reporting interval if enable is set to true. 248 * @param instanceId the nanoapp instance ID that owns the request. 249 * @return true if the location session request list was updated. 250 */ 251 bool updateLocationSessionRequests(bool enable, Milliseconds minInterval, 252 uint32_t instanceId); 253 254 /** 255 * Posts the result of a GNSS location session start/stop request. 256 * 257 * @param instanceId The nanoapp instance ID that made the request. 258 * @param success true if the operation was successful. 259 * @param enable true if enabling the location session. 260 * @param minInterval the minimum location reporting interval. 261 * @param errorCode the error code as a result of this operation. 262 * @param cookie the cookie that the nanoapp is provided for context. 263 * @return true if the event was successfully posted. 264 */ 265 bool postLocationSessionAsyncResultEvent( 266 uint32_t instanceId, bool success, bool enable, Milliseconds minInterval, 267 uint8_t errorCode, const void *cookie); 268 269 /** 270 * Calls through to postLocationSessionAsyncResultEvent but invokes 271 * FATAL_ERROR if the event is not posted successfully. This is used in 272 * asynchronous contexts where a nanoapp could be stuck waiting for a response 273 * but CHRE failed to enqueue one. For parameter details, 274 * @see postLocationSessionAsyncResultEvent 275 */ 276 void postLocationSessionAsyncResultEventFatal( 277 uint32_t instanceId, bool success, bool enable, Milliseconds minInterval, 278 uint8_t errorCode, const void *cookie); 279 280 /** 281 * Handles the result of a request to PlatformGnss to change the state of the 282 * scan monitor. See the handleLocationSessionStatusChange method which may be 283 * called from any thread. This method is intended to be invoked on the CHRE 284 * event loop thread. 285 * 286 * @param enabled true if the location session was enabled 287 * @param errorCode an error code that is provided to indicate success. 288 */ 289 void handleLocationSessionStatusChangeSync(bool enabled, uint8_t errorCode); 290 291 /** 292 * Handles the releasing of a GNSS location event. 293 * 294 * @param event The event to free. 295 */ 296 void handleFreeLocationEvent(chreGnssLocationEvent *event); 297 298 /** 299 * Releases a GNSS location event after nanoapps have consumed it. 300 * 301 * @param eventType the type of event being freed. 302 * @param eventData a pointer to the scan event to release. 303 */ 304 static void freeLocationEventCallback(uint16_t eventType, void *eventData); 305 }; 306 307 } // namespace chre 308 309 #endif // CHRE_CORE_GNSS_REQUEST_MANAGER_H_ 310