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/sensor.h"
21 #include "chre/core/sensor_request.h"
22 #include "chre/core/sensor_request_multiplexer.h"
23 #include "chre/platform/fatal_error.h"
24 #include "chre/platform/platform_sensor_manager.h"
25 #include "chre/platform/system_time.h"
26 #include "chre/platform/system_timer.h"
27 #include "chre/util/non_copyable.h"
28 #include "chre/util/optional.h"
29 #include "chre/util/system/debug_dump.h"
30 
31 namespace chre {
32 
33 /**
34  * Handles requests from nanoapps for sensor data and information. This includes
35  * multiplexing multiple requests into one for the platform to handle.
36  *
37  * This class is effectively a singleton as there can only be one instance of
38  * the PlatformSensorManager instance.
39  */
40 class SensorRequestManager : public NonCopyable {
41  public:
42   /**
43    * Destructs the sensor request manager and releases platform sensor resources
44    * if requested.
45    */
46   ~SensorRequestManager();
47 
48   /**
49    * Initializes the underlying platform-specific sensors. Must be called
50    * prior to invoking any other methods in this class.
51    */
52   void init();
53 
54   /**
55    * Determines whether the runtime is aware of a given sensor type. The
56    * supplied sensorHandle is only populated if the sensor type is known.
57    *
58    * @param sensorType The type of the sensor.
59    * @param sensorIndex The index of the sensor.
60    * @param targetGroupId The target group ID that must be covered by the
61    *     matching sensor.
62    * @param sensorHandle A non-null pointer to a uint32_t to use as a sensor
63    *                     handle for nanoapps.
64    * @return true if the supplied sensor type is available for use.
65    */
66   bool getSensorHandle(uint8_t sensorType, uint8_t sensorIndex,
67                        uint16_t targetGroupId, uint32_t *sensorHandle) const;
68 
69   /**
70    * Same as getSensorHandle(), but the targetGroupId is derived based on the
71    * nanoapp's characteristics.
72    */
getSensorHandleForNanoapp(uint8_t sensorType,uint8_t sensorIndex,const Nanoapp & nanoapp,uint32_t * sensorHandle)73   bool getSensorHandleForNanoapp(uint8_t sensorType, uint8_t sensorIndex,
74                                  const Nanoapp &nanoapp,
75                                  uint32_t *sensorHandle) const {
76     return getSensorHandle(sensorType, sensorIndex,
77                            mPlatformSensorManager.getTargetGroupId(nanoapp),
78                            sensorHandle);
79   }
80 
81   /**
82    * Same as getSensorHandle(), but 0 is used for both the sensorIndex and
83    * targetGroupId so that the first sensor matching the type is used. This is
84    * useful when dealing with one-shot sensors that must only have a single
85    * instance.
86    */
getDefaultSensorHandle(uint8_t sensorType,uint32_t * sensorHandle)87   bool getDefaultSensorHandle(uint8_t sensorType,
88                               uint32_t *sensorHandle) const {
89     return getSensorHandle(sensorType, 0 /* sensorIndex */,
90                            0 /* targetGroupId */, sensorHandle);
91   }
92 
93   /**
94    * Sets a sensor request for the given nanoapp for the provided sensor handle.
95    * If the nanoapp has made a previous request, it is replaced by this request.
96    * If the request changes the mode to SensorMode::Off the request is removed.
97    *
98    * @param nanoapp A non-null pointer to the nanoapp requesting this change.
99    * @param sensorHandle The sensor handle for which this sensor request is
100    *        directed at.
101    * @param request The new sensor request for this nanoapp.
102    * @return true if the request was set successfully. If the sensorHandle is
103    *         out of range or the platform sensor fails to update to the new
104    *         request false will be returned.
105    */
106   bool setSensorRequest(Nanoapp *nanoapp, uint32_t sensorHandle,
107                         const SensorRequest &sensorRequest);
108 
109   /**
110    * Populates the supplied info struct if the sensor handle exists.
111    *
112    * @param sensorHandle The handle of the sensor.
113    * @param nanoapp The nanoapp requesting this change.
114    * @param info A non-null pointer to a chreSensorInfo struct.
115    * @return true if the supplied sensor handle exists.
116    */
117   bool getSensorInfo(uint32_t sensorHandle, const Nanoapp &nanoapp,
118                      struct chreSensorInfo *info) const;
119   /*
120    * Removes all requests of a sensorType and unregisters all nanoapps for its
121    * events.
122    *
123    * @param sensorHandle The handle of the sensor.
124    * @return true if all requests of the sensor type have been successfully
125    *         removed.
126    */
127   bool removeAllRequests(uint32_t sensorHandle);
128 
129   /**
130    * Obtains a pointer to the Sensor of the specified sensorHandle.
131    *
132    * NOTE: Some platform implementations invoke this method from different
133    * threads assuming the underlying list of sensors doesn't change after
134    * initialization.
135    *
136    * @param sensorHandle The sensor handle corresponding to the sensor.
137    * @return A pointer to the Sensor, or nullptr if sensorHandle is invalid.
138    */
139   Sensor *getSensor(uint32_t sensorHandle);
140 
141   /**
142    * Populates the supplied sampling status struct if the sensor handle exists.
143    *
144    * @param sensorHandle The handle of the sensor.
145    * @param status A non-null pointer to a chreSensorSamplingStatus struct.
146    * @return true if the supplied sensor handle exists.
147    */
148   bool getSensorSamplingStatus(uint32_t sensorHandle,
149                                struct chreSensorSamplingStatus *status) const;
150 
151   /**
152    * Obtains the list of open requests of the specified sensor handle.
153    *
154    * @param sensorHandle The handle of the sensor.
155    * @return The list of open requests of this sensor in a DynamicVector.
156    */
157   const DynamicVector<SensorRequest> &getRequests(uint32_t sensorHandle) const;
158 
159   /**
160    * Configures a nanoapp to receive bias events.
161    *
162    * @param nanoapp A non-null pointer to the nanoapp making this request.
163    * @param sensorHandle The handle of the sensor to receive bias events for.
164    * @param enable true to enable bias event reporting.
165    *
166    * @return true if the configuration was successful.
167    */
168   bool configureBiasEvents(Nanoapp *nanoapp, uint32_t sensorHandle,
169                            bool enable);
170 
171   /**
172    * Synchronously retrieves the current bias for a sensor that supports
173    * data in the chreSensorThreeAxisData format.
174    *
175    * @param sensorHandle The handle of the sensor to retrieve bias data for.
176    * @param bias A non-null pointer to store the current bias data.
177    *
178    * @return false if the sensor handle was invalid or the sensor does not
179    *     report bias data in the chreSensorThreeAxisData format.
180    */
181   bool getThreeAxisBias(uint32_t sensorHandle,
182                         struct chreSensorThreeAxisData *bias) const;
183 
184   /**
185    * Makes a sensor flush request for a nanoapp asynchronously.
186    *
187    * @param nanoapp A non-null pointer to the nanoapp requesting this change.
188    * @param sensorHandle The sensor handle for which this sensor request is
189    *        directed at.
190    * @param cookie An opaque pointer to data that will be used in the
191    *        chreSensorFlushCompleteEvent.
192    *
193    * @return true if the request was accepted, false otherwise
194    */
195   bool flushAsync(Nanoapp *nanoapp, uint32_t sensorHandle, const void *cookie);
196 
197   /**
198    * Invoked by the PlatformSensorManager when a flush complete event is
199    * received for a given sensor for a request done through flushAsync(). This
200    * method can be invoked from any thread, and defers processing the event to
201    * the main CHRE event loop.
202    *
203    * @param sensorHandle The sensor handle that completed flushing.
204    * @param flushRequestId The ID of the flush request that completed. Should
205    *     be set to UINT32_MAX if request IDs are not supported by the platform.
206    * @param errorCode An error code from enum chreError
207    */
208   void handleFlushCompleteEvent(uint32_t sensorHandle, uint32_t flushRequestId,
209                                 uint8_t errorCode);
210 
211   /**
212    * Invoked by the PlatformSensorManager when a sensor event is received for a
213    * given sensor. This method should be invoked from the same thread.
214    *
215    * @param sensorHandle The sensor handle this data event is from.
216    * @param event the event data formatted as one of the chreSensorXXXData
217    *     defined in the CHRE API, implicitly specified by sensorHandle.
218    */
219   void handleSensorDataEvent(uint32_t sensorHandle, void *event);
220 
221   /**
222    * Invoked by the PlatformSensorManager when a sensor's sampling status
223    * changes. This method can be invoked from any thread.
224    *
225    * @param sensorHandle The handle that corresponds to the sensor this update
226    *     is for.
227    * @param status The status update for the given sensor.
228    */
229   void handleSamplingStatusUpdate(uint32_t sensorHandle,
230                                   struct chreSensorSamplingStatus *status);
231 
232   /**
233    * Invoked by the PlatformSensorManager when a bias update has been received
234    * for a sensor. This method can be invoked from any thread.
235    *
236    * @param sensorHandle The handle that corresponds to the sensor this update
237    *     is for.
238    * @param bias The bias update for the given sensor.
239    */
240   void handleBiasEvent(uint32_t sensorHandle, void *biasData);
241 
242   /**
243    * Prints state in a string buffer. Must only be called from the context of
244    * the main CHRE thread.
245    *
246    * @param debugDump The debug dump wrapper where a string can be printed
247    *     into one of the buffers.
248    */
249   void logStateToBuffer(DebugDumpWrapper &debugDump) const;
250 
251   /**
252    * Releases the sensor data event back to the platform. Also removes any
253    * requests for a one-shot sensor if the sensor type corresponds to a one-shot
254    * sensor.
255    *
256    * @param eventType the sensor event type that was sent and now needs to be
257    *     released.
258    * @param eventData the event data to be released back to the platform.
259    */
260   void releaseSensorDataEvent(uint16_t eventType, void *eventData);
261 
262   /**
263    * Releases the bias data back to the platform.
264    *
265    * @param biasData the bias data to be released back to the platform.
266    */
releaseBiasData(void * biasData)267   void releaseBiasData(void *biasData) {
268     mPlatformSensorManager.releaseBiasEvent(biasData);
269   }
270 
271   /**
272    * Releases the sampling status updated back to the platform.
273    *
274    * @param status the status to be released back to the platform.
275    */
releaseSamplingStatusUpdate(struct chreSensorSamplingStatus * status)276   void releaseSamplingStatusUpdate(struct chreSensorSamplingStatus *status) {
277     mPlatformSensorManager.releaseSamplingStatusUpdate(status);
278   }
279 
280  private:
281   //! An internal structure to store incoming sensor flush requests
282   struct FlushRequest {
FlushRequestFlushRequest283     FlushRequest(uint32_t handle, uint32_t id, const void *cookiePtr) {
284       sensorHandle = handle;
285       nanoappInstanceId = id;
286       cookie = cookiePtr;
287     }
288 
289     //! The timestamp at which this request should complete.
290     Nanoseconds deadlineTimestamp =
291         SystemTime::getMonotonicTime() +
292         Nanoseconds(CHRE_SENSOR_FLUSH_COMPLETE_TIMEOUT_NS);
293     //! The sensor handle this flush request is for.
294     uint32_t sensorHandle;
295     //! The ID of the nanoapp that requested the flush.
296     uint32_t nanoappInstanceId;
297     //! The opaque pointer provided in flushAsync().
298     const void *cookie;
299     //! True if this flush request is active and is pending completion.
300     bool isActive = false;
301   };
302 
303   //! An internal structure to store sensor request logs
304   struct SensorRequestLog {
SensorRequestLogSensorRequestLog305     SensorRequestLog(Nanoseconds timestampIn, uint32_t instanceIdIn,
306                      uint32_t sensorHandleIn, SensorMode modeIn,
307                      Nanoseconds intervalIn, Nanoseconds latencyIn)
308         : timestamp(timestampIn),
309           interval(intervalIn),
310           latency(latencyIn),
311           instanceId(instanceIdIn),
312           sensorHandle(sensorHandleIn),
313           mode(modeIn) {}
314 
315     Nanoseconds timestamp;
316     Nanoseconds interval;
317     Nanoseconds latency;
318     uint32_t instanceId;
319     uint32_t sensorHandle;
320     SensorMode mode;
321   };
322 
323   //! The list of all sensors
324   DynamicVector<Sensor> mSensors;
325 
326   //! The list of logged sensor requests
327   static constexpr size_t kMaxSensorRequestLogs = 15;
328   ArrayQueue<SensorRequestLog, kMaxSensorRequestLogs> mSensorRequestLogs;
329 
330   //! A queue of flush requests made by nanoapps.
331   static constexpr size_t kMaxFlushRequests = 16;
332   FixedSizeVector<FlushRequest, kMaxFlushRequests> mFlushRequestQueue;
333 
334   PlatformSensorManager mPlatformSensorManager;
335 
336   /**
337    * Makes a specified flush request, and sets the timeout timer appropriately.
338    * If there already is a pending flush request for the sensor specified in
339    * the request, then this method does nothing.
340    *
341    * @param request the request to make
342    *
343    * @return An error code from enum chreError
344    */
345   uint8_t makeFlushRequest(FlushRequest &request);
346 
347   /**
348    * Make a flush request through PlatformSensorManager.
349    *
350    * @param sensor The sensor to flush.
351    * @return true if the flush request was successfully made.
352    */
353   bool doMakeFlushRequest(Sensor &sensor);
354 
355   /**
356    * Removes all requests and consolidates all the maximal request changes
357    * into one sensor configuration update.
358    *
359    * @param sensor The sensor to clear all requests for.
360    * @return true if all the requests have been removed and sensor
361    *         configuration successfully updated.
362    */
363   bool removeAllRequests(Sensor &sensor);
364 
365   /**
366    * Removes a sensor request from the given lists of requests. The provided
367    * index must fall in the range of the sensor requests available.
368    *
369    * @param sensor The sensor to remove the request from.
370    * @param removeIndex The index to remove the request from.
371    * @param requestChanged A non-null pointer to a bool to indicate that the
372    *        net request made to the sensor has changed. This boolean is always
373    *        assigned to the status of the request changing (true or false).
374    * @return true if the remove operation was successful.
375    */
376   bool removeRequest(Sensor &sensor, size_t removeIndex, bool *requestChanged);
377 
378   /**
379    * Adds a new sensor request to the given list of requests.
380    *
381    * @param sensor The sensor to add the request to.
382    * @param request The request to add to the multiplexer.
383    * @param requestChanged A non-null pointer to a bool to indicate that the
384    *        net request made to the sensor has changed. This boolean is always
385    *        assigned to the status of the request changing (true or false).
386    * @return true if the add operation was successful.
387    */
388   bool addRequest(Sensor &sensor, const SensorRequest &request,
389                   bool *requestChanged);
390 
391   /**
392    * Updates a sensor request in the given list of requests. The provided index
393    * must fall in range of the sensor requests managed by the multiplexer.
394    *
395    * @param sensor The sensor that will be updated.
396    * @param updateIndex The index to update the request at.
397    * @param request The new sensor request to replace the existing request
398    *        with.
399    * @param requestChanged A non-null pointer to a bool to indicate that the
400    *        net request made to the sensor has changed. This boolean is always
401    *        assigned to the status of the request changing (true or false).
402    * @return true if the update operation was successful.
403    */
404   bool updateRequest(Sensor &sensor, size_t updateIndex,
405                      const SensorRequest &request, bool *requestChanged);
406 
407   /**
408    * Posts an event to a nanoapp indicating the completion of a flush request.
409    *
410    * @param sensorHandle The handle of the sensor for this event.
411    * @param errorCode An error code from enum chreError
412    * @param request The corresponding FlushRequest.
413    */
414   void postFlushCompleteEvent(uint32_t sensorHandle, uint8_t errorCode,
415                               const FlushRequest &request);
416 
417   /**
418    * Completes a flush request at the specified index by posting a
419    * CHRE_EVENT_SENSOR_FLUSH_COMPLETE event with the specified errorCode,
420    * removing the request from the queue, cleaning up states as necessary.
421    *
422    * @param index The index of the flush request.
423    * @param errorCode The error code to send the completion event with.
424    */
425   void completeFlushRequestAtIndex(size_t index, uint8_t errorCode);
426 
427   /**
428    * Dispatches the next flush request for the given sensor. If there are no
429    * more pending flush requests, this method does nothing.
430    *
431    * @param sensorHandle The handle of the sensor to dispatch a new flush
432    *     request for.
433    */
434   void dispatchNextFlushRequest(uint32_t sensorHandle);
435 
436   /**
437    * A method that is called whenever a flush request times out.
438    *
439    * @param sensorHandle The sensor handle of the flush request.
440    */
441   void onFlushTimeout(uint32_t sensorHandle);
442 
443   /**
444    * Handles a complete event for a sensor flush requested through flushAsync.
445    * See handleFlushCompleteEvent which may be called from any thread. This
446    * method is intended to be invoked on the CHRE event loop thread.
447    *
448    * @param errorCode An error code from enum chreError
449    * @param sensorHandle The handle of the sensor that has completed the flush.
450    */
451   void handleFlushCompleteEventSync(uint8_t errorCode, uint32_t sensorHandle);
452 
453   /**
454    * Cancels all pending flush requests for a given sensor and nanoapp.
455    *
456    * @param sensorHandle The sensor handle indicating the sensor to cancel flush
457    *     requests for.
458    * @param nanoappInstanceId The ID of the nanoapp to cancel requests for,
459    *     kSystemInstanceId to remove requests for all nanoapps.
460    */
461   void cancelFlushRequests(uint32_t sensorHandle,
462                            uint32_t nanoappInstanceId = kSystemInstanceId);
463 
464   /**
465    * Adds a request log to the list of logs possibly pushing latest log
466    * off if full.
467    *
468    * @param nanoappInstanceId Instance ID of the nanoapp that made the request.
469    * @param sensorHandle The sensor handle for the sensor request being added.
470    * @param sensorRequest The SensorRequest object holding params about
471    *    request.
472    */
473   void addSensorRequestLog(uint32_t nanoappInstanceId, uint32_t sensorHandle,
474                            const SensorRequest &sensorRequest);
475 
476   /**
477    * Helper function to make a sensor's maximal request to the platform, and
478    * reset the last event if an on-change sensor is successfully turned off.
479    *
480    * If either bias update configuration or sensor data configuration fails,
481    * this entire method will fail. When this method fails, any previous
482    * configuration will be restored on a best-effort basis.
483    *
484    * @param sensor The sensor that will be configured.
485    * @param prevSensorRequest The previous sensor request that was made for the
486    *     given sensor.
487    * @return true if both configuring the platform for bias updates and for
488    *     sensor data succeeded.
489    */
490   bool configurePlatformSensor(Sensor &sensor,
491                                const SensorRequest &prevSensorRequest);
492 
493   /**
494    * @param nanoappInstanceId The instance ID of the nanoapp to check.
495    * @param sensorType The sensor type.
496    *
497    * @return the target group masks that are actively enabled for this nanoapp
498    *  and the sensor type.
499    */
500   uint16_t getActiveTargetGroupMask(uint32_t nanoappInstanceId,
501                                     uint8_t sensorType);
502 };
503 
504 }  // namespace chre
505 
506 #endif  // CHRE_CORE_SENSOR_REQUEST_MANAGER_H_
507