• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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