1 /*
2  * Copyright (C) 2016 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_SENSOR_REQUEST_MANAGER_H_
18 #define CHRE_CORE_SENSOR_REQUEST_MANAGER_H_
19 
20 #include "chre/core/request_multiplexer.h"
21 #include "chre/core/sensor.h"
22 #include "chre/core/sensor_request.h"
23 #include "chre/core/timer_pool.h"
24 #include "chre/platform/atomic.h"
25 #include "chre/platform/system_time.h"
26 #include "chre/platform/system_timer.h"
27 #include "chre/util/fixed_size_vector.h"
28 #include "chre/util/non_copyable.h"
29 #include "chre/util/optional.h"
30 
31 namespace chre {
32 
33 class SensorRequestManager : public NonCopyable {
34  public:
35   /**
36    * Performs initialization of the SensorRequestManager and populates the
37    * sensor list with platform sensors.
38    */
39   SensorRequestManager();
40 
41   /**
42    * Destructs the sensor request manager and releases platform sensor resources
43    * if requested.
44    */
45   ~SensorRequestManager();
46 
47   /**
48    * Initializes the underlying platform-specific sensors. Must be called
49    * prior to invoking any other methods in this class.
50    */
51   void init();
52 
53   /**
54    * Determines whether the runtime is aware of a given sensor type. The
55    * supplied sensorHandle is only populated if the sensor type is known.
56    *
57    * @param sensorType The type of the sensor.
58    * @param sensorHandle A non-null pointer to a uint32_t to use as a sensor
59    *                     handle for nanoapps.
60    * @return true if the supplied sensor type is available for use.
61    */
62   bool getSensorHandle(SensorType sensorType, uint32_t *sensorHandle) const;
63 
64   /**
65    * Sets a sensor request for the given nanoapp for the provided sensor handle.
66    * If the nanoapp has made a previous request, it is replaced by this request.
67    * If the request changes the mode to SensorMode::Off the request is removed.
68    *
69    * @param nanoapp A non-null pointer to the nanoapp requesting this change.
70    * @param sensorHandle The sensor handle for which this sensor request is
71    *        directed at.
72    * @param request The new sensor request for this nanoapp.
73    * @return true if the request was set successfully. If the sensorHandle is
74    *         out of range or the platform sensor fails to update to the new
75    *         request false will be returned.
76    */
77   bool setSensorRequest(Nanoapp *nanoapp, uint32_t sensorHandle,
78                         const SensorRequest& sensorRequest);
79 
80   /**
81    * Populates the supplied info struct if the sensor handle exists.
82    *
83    * @param sensorHandle The handle of the sensor.
84    * @param nanoapp The nanoapp requesting this change.
85    * @param info A non-null pointer to a chreSensorInfo struct.
86    * @return true if the supplied sensor handle exists.
87    */
88   bool getSensorInfo(uint32_t sensorHandle, const Nanoapp& nanoapp,
89                      struct chreSensorInfo *info) const;
90   /*
91    * Removes all requests of a sensorType and unregisters all nanoapps for its
92    * events.
93    *
94    * @param sensorType The sensor type whose requests are to be removed.
95    * @return true if all requests of the sensor type have been successfully
96    *         removed.
97    */
98   bool removeAllRequests(SensorType sensorType);
99 
100   /**
101    * Obtains a pointer to the Sensor of the specified sensorType.
102    *
103    * NOTE: Some platform implementations invoke this method from different
104    * threads assuming the underlying list of sensors doesn't change after
105    * initialization.
106    *
107    * @param sensorType The SensorType of the sensor.
108    * @return A pointer to the Sensor of sensorType, or nullptr if sensorType is
109    *         invalid or the requested SensorType is not supported on the current
110    *         platform.
111    */
112   Sensor *getSensor(SensorType sensorType);
113 
114   /**
115    * Populates the supplied sampling status struct if the sensor handle exists.
116    *
117    * @param sensorHandle The handle of the sensor.
118    * @param status A non-null pointer to a chreSensorSamplingStatus struct.
119    * @return true if the supplied sensor handle exists.
120    */
121   bool getSensorSamplingStatus(uint32_t sensorHandle,
122                                struct chreSensorSamplingStatus *status) const;
123 
124   /**
125    * Obtains the list of open requests of the specified SensorType.
126    *
127    * @param sensorType The SensorType of the sensor.
128    * @return The list of open requests of this sensor in a DynamicVector.
129    */
130   const DynamicVector<SensorRequest>& getRequests(SensorType sensorType) const;
131 
132   /**
133    * Configures a nanoapp to receive bias events.
134    *
135    * @param nanoapp A non-null pointer to the nanoapp making this request.
136    * @param sensorHandle The handle of the sensor to receive bias events for.
137    * @param enable true to enable bias event reporting.
138    *
139    * @return true if the configuration was successful.
140    */
141   bool configureBiasEvents(
142       Nanoapp *nanoapp, uint32_t sensorHandle, bool enable);
143 
144   /**
145    * Synchronously retrieves the current bias for a sensor that supports
146    * data in the chreSensorThreeAxisData format.
147    *
148    * @param sensorHandle The handle of the sensor to retrieve bias data for.
149    * @param bias A non-null pointer to store the current bias data.
150    *
151    * @return false if the sensor handle was invalid or the sensor does not
152    *     report bias data in the chreSensorThreeAxisData format.
153    */
154   bool getThreeAxisBias(
155       uint32_t sensorHandle, struct chreSensorThreeAxisData *bias) const;
156 
157   /**
158    * Makes a sensor flush request for a nanoapp asynchronously.
159    *
160    * @param nanoapp A non-null pointer to the nanoapp requesting this change.
161    * @param sensorHandle The sensor handle for which this sensor request is
162    *        directed at.
163    * @param cookie An opaque pointer to data that will be used in the
164    *        chreSensorFlushCompleteEvent.
165    *
166    * @return true if the request was accepted, false otherwise
167    */
168   bool flushAsync(Nanoapp *nanoapp, uint32_t sensorHandle, const void *cookie);
169 
170   /**
171    * Invoked by the PlatformSensor when a flush complete event is received for a
172    * given sensor for a request done through flushAsync(). This method can be
173    * invoked from any thread, and defers processing the event to the main CHRE
174    * event loop.
175    *
176    * @param errorCode An error code from enum chreError
177    * @param sensorType The SensorType of sensor that has completed the flush.
178    */
179   void handleFlushCompleteEvent(uint8_t errorCode, SensorType sensorType);
180 
181   /**
182    * Invoked by the PlatformSensor when a sensor event is received for a given
183    * sensor. This method should be invoked from the same thread.
184    *
185    * @param sensorType the type of sensor the sensor data corresponds to
186    * @param event the event data formatted as one of the chreSensorXXXData
187    *     defined in the CHRE API, implicitly specified by sensorType.
188    */
189   void handleSensorEvent(SensorType sensorType, void *event);
190 
191   /**
192    * Prints state in a string buffer. Must only be called from the context of
193    * the main CHRE thread.
194    *
195    * @param buffer Pointer to the start of the buffer.
196    * @param bufferPos Pointer to buffer position to start the print (in-out).
197    * @param size Size of the buffer in bytes.
198    */
199   void logStateToBuffer(char *buffer, size_t *bufferPos,
200                         size_t bufferSize) const;
201 
202  private:
203   //! An internal structure to store incoming sensor flush requests
204   struct FlushRequest {
FlushRequestFlushRequest205     FlushRequest(SensorType type, uint32_t id, const void *cookiePtr) {
206       sensorType = type;
207       nanoappInstanceId = id;
208       cookie = cookiePtr;
209     }
210 
211     //! The sensor type the flush request is for.
212     SensorType sensorType;
213     //! The ID of the nanoapp that requested the flush.
214     uint32_t nanoappInstanceId;
215     //! The opaque pointer provided in flushAsync().
216     const void *cookie;
217     //! The timestamp at which this request should complete.
218     Nanoseconds deadlineTimestamp = SystemTime::getMonotonicTime() +
219         Nanoseconds(CHRE_SENSOR_FLUSH_COMPLETE_TIMEOUT_NS);
220     //! True if this flush request is active and is pending completion.
221     bool isActive = false;
222   };
223 
224   /**
225    * This allows tracking the state of a sensor with the various requests for it
226    * and can trigger a change in mode/rate/latency when required.
227    */
228   class SensorRequests {
229    public:
SensorRequests()230     SensorRequests() : mFlushRequestPending(false) {}
231 
232      /**
233       * Initializes the sensor object. This method must only be invoked once
234       * when the SensorRequestManager initializes.
235       *
236       * @param sensor The sensor object to initialize with.
237       */
setSensor(Sensor && sensor)238     void setSensor(Sensor&& sensor) {
239       CHRE_ASSERT(!mSensor.has_value());
240       mSensor = std::move(sensor);
241     }
242 
243     /**
244      * @return true if the sensor is supported by the platform.
245      */
isSensorSupported()246     bool isSensorSupported() const {
247       return mSensor.has_value();
248     }
249 
250     /**
251      * @return The set of active requests for this sensor.
252      */
getRequests()253     const DynamicVector<SensorRequest>& getRequests() const {
254       return mMultiplexer.getRequests();
255     }
256 
257     /**
258      * @return true if the sensor is currently enabled.
259      */
isSensorEnabled()260     bool isSensorEnabled() const {
261       return !mMultiplexer.getRequests().empty();
262     }
263 
264     /**
265      * @return A constant reference to the sensor object. This method has an
266      * undefined behavior if isSensorSupported() is false.
267      */
getSensor()268     const Sensor& getSensor() const {
269       return mSensor.value();
270     }
271 
272     /**
273      * @return A reference to the sensor object. This method has an undefined
274      * behavior if isSensorSupported() is false.
275      */
getSensor()276     Sensor& getSensor() {
277       return mSensor.value();
278     }
279 
280     /**
281      * Gets the sensor's sampling status. The caller must ensure that
282      * isSensorSupported() is true before invoking this method.
283      *
284      * @param status A non-null pointer where the sampling status will be
285      * stored, if successful.
286      *
287      * @return true if getting the sampling status succeeded.
288      */
getSamplingStatus(struct chreSensorSamplingStatus * status)289     bool getSamplingStatus(struct chreSensorSamplingStatus *status) const {
290       CHRE_ASSERT(isSensorSupported());
291       return isSensorSupported() ? mSensor->getSamplingStatus(status) : false;
292     }
293 
294     /**
295      * Synchronously retrieves the current bias for a sensor that supports
296      * data in the chreSensorThreeAxisData format. The caller must ensure that
297      * isSensorSupported() is true before invoking this method.
298      *
299      * @param bias A non-null pointer to store the current bias data.
300      *
301      * @return false if sensor does not report bias data in the
302      *     chreSensorThreeAxisData format.
303      */
getThreeAxisBias(struct chreSensorThreeAxisData * bias)304     bool getThreeAxisBias(struct chreSensorThreeAxisData *bias) const {
305       CHRE_ASSERT(isSensorSupported());
306       return isSensorSupported() ? mSensor->getThreeAxisBias(bias) : false;
307     }
308 
309     /**
310      * Searches through the list of sensor requests for a request owned by the
311      * given nanoapp. The provided non-null index pointer is populated with the
312      * index of the request if it is found.
313      *
314      * @param instanceId The instance ID of the nanoapp whose request is being
315      *        searched for.
316      * @param index A non-null pointer to an index that is populated if a
317      *        request for this nanoapp is found.
318      * @return A pointer to a SensorRequest that is owned by the provided
319      *         nanoapp if one is found otherwise nullptr.
320      */
321     const SensorRequest *find(uint32_t instanceId, size_t *index) const;
322 
323     /**
324      * Adds a new sensor request to the request multiplexer for this sensor.
325      *
326      * @param request The request to add to the multiplexer.
327      * @param requestChanged A non-null pointer to a bool to indicate that the
328      *        net request made to the sensor has changed. This boolean is always
329      *        assigned to the status of the request changing (true or false).
330      * @return true if the add operation was successful.
331      */
332     bool add(const SensorRequest& request, bool *requestChanged);
333 
334     /**
335      * Removes a sensor request from the request multiplexer for this sensor.
336      * The provided index must fall in the range of the sensor requests managed
337      * by the multiplexer.
338      *
339      * @param removeIndex The index to remove the request from.
340      * @param requestChanged A non-null pointer to a bool to indicate that the
341      *        net request made to the sensor has changed. This boolean is always
342      *        assigned to the status of the request changing (true or false).
343      * @return true if the remove operation was successful.
344      */
345     bool remove(size_t removeIndex, bool *requestChanged);
346 
347     /**
348      * Updates a sensor request in the request multiplexer for this sensor. The
349      * provided index must fall in range of the sensor requests managed by the
350      * multiplexer.
351      *
352      * @param updateIndex The index to update the request at.
353      * @param request The new sensor request to replace the existing request
354      *        with.
355      * @return true if the update operation was successful.
356      */
357     bool update(size_t updateIndex, const SensorRequest& request,
358                 bool *requestChanged);
359 
360     /**
361      * Removes all requests and consolidates all the maximal request changes
362      * into one sensor configuration update.
363      *
364      * @return true if all the requests have been removed and sensor
365      *         configuration successfully updated.
366      */
367     bool removeAll();
368 
369     /**
370      * Makes a specified flush request for this sensor, and sets the timeout
371      * timer appropriately. If there already is a pending flush request, then
372      * this method does nothing.
373      *
374      * @param request the request to make
375      *
376      * @return An error code from enum chreError
377      */
378     uint8_t makeFlushRequest(FlushRequest& request);
379 
380     /**
381      * Clears any states (e.g. timeout timer and relevant flags) associated
382      * with a pending flush request.
383      */
384     void clearPendingFlushRequest();
385 
386     /**
387      * Cancels the pending timeout timer associated with a flush request.
388      */
389     void cancelPendingFlushRequestTimer();
390 
391     /**
392      * @return true if a flush through makeFlushRequest is pending.
393      */
isFlushRequestPending()394     inline bool isFlushRequestPending() const {
395       return mFlushRequestPending;
396     }
397 
398    private:
399     //! The sensor associated with this request multiplexer. If this Optional
400     //! container does not have a value, then the platform does not support this
401     //! type of sensor.
402     Optional<Sensor> mSensor;
403 
404     //! The request multiplexer for this sensor.
405     RequestMultiplexer<SensorRequest> mMultiplexer;
406 
407     //! The timeout timer handle for the current flush request.
408     TimerHandle mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
409 
410     //! True if a flush request is pending for this sensor.
411     AtomicBool mFlushRequestPending;
412 
413     /**
414      * Make a flush request through PlatformSensor.
415      *
416      * @return true if the flush request was successfully made.
417      */
418     bool doMakeFlushRequest();
419   };
420 
421   //! The list of sensor requests.
422   FixedSizeVector<SensorRequests, getSensorTypeCount()> mSensorRequests;
423 
424   //! A queue of flush requests made by nanoapps.
425   static constexpr size_t kMaxFlushRequests = 16;
426   FixedSizeVector<FlushRequest, kMaxFlushRequests> mFlushRequestQueue;
427 
428   /**
429    * Helper function to convert SensorType to SensorRequests.
430    */
getSensorRequests(SensorType sensorType)431   SensorRequests& getSensorRequests(SensorType sensorType) {
432     size_t index = getSensorTypeArrayIndex(sensorType);
433     return mSensorRequests[index];
434   }
435 
436   /**
437    * Posts an event to a nanoapp indicating the completion of a flush request.
438    *
439    * @param sensorHandle The handle of the sensor for this event.
440    * @param errorCode An error code from enum chreError
441    * @param request The corresponding FlushRequest.
442    */
443   void postFlushCompleteEvent(
444     uint32_t sensorHandle, uint8_t errorCode, const FlushRequest& request);
445 
446   /**
447    * Completes a flush request at the specified index by posting a
448    * CHRE_EVENT_SENSOR_FLUSH_COMPLETE event with the specified errorCode,
449    * removing the request from the queue, cleaning up states as necessary.
450    *
451    * @param index The index of the flush request.
452    * @param errorCode The error code to send the completion event with.
453    */
454   void completeFlushRequestAtIndex(size_t index, uint8_t errorCode);
455 
456   /**
457    * Dispatches the next flush request for the given sensor. If there are no
458    * more pending flush requests, this method does nothing.
459    *
460    * @param sensorType The corresponding sensor type.
461    */
462   void dispatchNextFlushRequest(SensorType sensorType);
463 
464   /**
465    * Handles a complete event for a sensor flush requested through flushAsync.
466    * See handleFlushCompleteEvent which may be called from any thread. This
467    * method is intended to be invoked on the CHRE event loop thread.
468    *
469    * @param errorCode An error code from enum chreError
470    * @param sensorType The SensorType of sensor that has completed the flush.
471    */
472   void handleFlushCompleteEventSync(uint8_t errorCode, SensorType sensorType);
473 
474   /**
475    * Cancels all pending flush requests for a given sensor and nanoapp.
476    *
477    * @param sensorType The type of sensor to cancel requests for.
478    * @param nanoappInstanceId The ID of the nanoapp to cancel requests for,
479    *     kSystemInstanceId to remove requests for all nanoapps.
480    */
481   void cancelFlushRequests(
482       SensorType sensorType, uint32_t nanoappInstanceId = kSystemInstanceId);
483 };
484 
485 }  // namespace chre
486 
487 #endif  // CHRE_CORE_SENSOR_REQUEST_MANAGER_H_
488