• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PLATFORM_SLPI_SEE_SEE_HELPER_H_
18 #define CHRE_PLATFORM_SLPI_SEE_SEE_HELPER_H_
19 
20 extern "C" {
21 
22 #include "sns_client.h"
23 
24 }  // extern "C"
25 
26 #include "sns_suid.pb.h"
27 
28 #include "chre/core/sensor_type.h"
29 #include "chre/platform/condition_variable.h"
30 #include "chre/platform/mutex.h"
31 #include "chre/platform/slpi/see/see_cal_helper.h"
32 #include "chre/util/dynamic_vector.h"
33 #include "chre/util/non_copyable.h"
34 #include "chre/util/optional.h"
35 #include "chre/util/time.h"
36 #include "chre/util/unique_ptr.h"
37 
38 namespace chre {
39 
suidsMatch(const sns_std_suid & suid0,const sns_std_suid & suid1)40 inline bool suidsMatch(const sns_std_suid& suid0, const sns_std_suid& suid1) {
41   return (suid0.suid_high == suid1.suid_high
42           && suid0.suid_low == suid1.suid_low);
43 }
44 
45 //! A callback interface for receiving SeeHelper data events.
46 class SeeHelperCallbackInterface {
47  public:
48   struct SamplingStatusData {
49     SensorType sensorType;
50     struct chreSensorSamplingStatus status;
51     bool enabledValid;
52     bool intervalValid;
53     bool latencyValid;
54   };
55 
~SeeHelperCallbackInterface()56   virtual ~SeeHelperCallbackInterface() {}
57 
58   //! Invoked by the SEE thread to update sampling status.
59   virtual void onSamplingStatusUpdate(
60       UniquePtr<SamplingStatusData>&& status) = 0;
61 
62   //! Invoked by the SEE thread to provide sensor data events. The event data
63   //! format is one of the chreSensorXXXData defined in the CHRE API, implicitly
64   //! specified by sensorType.
65   virtual void onSensorDataEvent(
66       SensorType sensorType, UniquePtr<uint8_t>&& eventData) = 0;
67 
68   //! Invoked by the SEE thread to update the AP wake/suspend status.
69   virtual void onHostWakeSuspendEvent(bool apAwake) = 0;
70 
71   //! Invoked by the SEE thread to provide the sensor bias event.
72   //! The bias is generated with the sensorHandle field set to that of
73   //! runtime-calibrated sensors, regardless of whether the runtime-calibrated
74   //! or uncalibrated versions of the sensor is enabled.
75   virtual void onSensorBiasEvent(
76       UniquePtr<struct chreSensorThreeAxisData>&& biasData) = 0;
77 
78   //! Invoked by the SEE thread to notify a flush complete
79   virtual void onFlushCompleteEvent(SensorType sensorType) = 0;
80 };
81 
82 //! Default timeout for waitForService. Have a longer timeout since there may be
83 //! external dependencies blocking SEE initialization.
84 constexpr Nanoseconds kDefaultSeeWaitTimeout = Seconds(5);
85 
86 //! Default timeout for sendReq response
87 constexpr Nanoseconds kDefaultSeeRespTimeout = Seconds(1);
88 
89 //! Default timeout for sendReq indication
90 constexpr Nanoseconds kDefaultSeeIndTimeout = Seconds(2);
91 
92 //! Allowed number of consecutive missing responses.
93 constexpr uint32_t kSeeNumMissingResp = 5;
94 
95 //! Length of the char array to store sensor string attributes.
96 constexpr size_t kSeeAttrStrValLen = 64;
97 
98 //! A struct to facilitate getAttributesSync().
99 struct SeeAttributes {
100   char vendor[kSeeAttrStrValLen];
101   char name[kSeeAttrStrValLen];
102   char type[kSeeAttrStrValLen];
103   int64_t hwId;
104   float maxSampleRate;
105   uint8_t streamType;
106   bool passiveRequest;
107 };
108 
109 //! A struct to facilitate making sensor request
110 struct SeeSensorRequest {
111   SensorType sensorType;
112   bool enable;
113   bool passive;
114   float samplingRateHz;
115   uint32_t batchPeriodUs;
116 };
117 
118 /**
119  * A helper class for making requests to Qualcomm's Sensors Execution
120  * Environment (SEE) via the sns_client API and waiting for the response and the
121  * corresponding indication message if applicable.
122  * Not safe to use from multiple threads. Only one synchronous request can be
123  * made at a time.
124  */
125 class SeeHelper : public NonCopyable {
126  public:
127   //! A struct to facilitate mapping between 'SUID + sns_client' and
128   //! SensorType.
129   struct SensorInfo {
130     sns_std_suid suid;
131     SensorType sensorType;
132     sns_client *client;
133     //! The SUID of the underlying physical sensor, different from suid if
134     //! resampler is used.
135     sns_std_suid physicalSuid;
136   };
137 
138   /**
139    * Constructor for a SeeHelper that manages its own SeeCalHelper
140    */
141   SeeHelper();
142 
143   /**
144    * Constructor for a SeeHelper that uses the supplied SeeCalHelper object
145    * rather than creating its own. Caller must ensure that the lifetime of the
146    * SeeCalHelper object exceeds the lifetime of this SeeHelper instance.
147    *
148    * TODO: this would be a good case for a shared ptr implementation
149    *
150    * @param calHelper Non-null pointer to a calibration helper object to use
151    */
152   SeeHelper(SeeCalHelper *calHelper);
153 
154   /**
155    * Deinits clients before destructing this object.
156    */
157   ~SeeHelper();
158 
159   /**
160    * Makes a request to SEE to enable an on-change sensor, with no additional
161    * payload. Can be used for registering a calibration sensor, for example.
162    *
163    * @param suid Sensor UID, usually determined via findSuidSync()
164    *
165    * @return true on success
166    */
167   bool configureOnChangeSensor(const sns_std_suid& suid, bool enable);
168 
169   /**
170    * A synchronous call to discover SUID(s) that supports the specified data
171    * type. This API will clear the provided dynamic vector before populating it.
172    *
173    * @param dataType A data type string, "accel" for example.
174    * @param suids A non-null pointer to a list of sensor UIDs that support the
175    *              specified data type.
176    * @param minNumSuids The minimum number of SUIDs it needs to find before
177    *                    returning true. Otherwise, it'll re-try internally
178    *                    until it times out. It's illegal to set it to 0.
179    * @param maxRetries Maximum amount of times to retry looking up the SUID
180    *                   until giving up.
181    * @param retryDelay Time delay between retry attempts (msec).
182    *
183    * @return true if at least minNumSuids were successfully found
184    */
185   bool findSuidSync(const char *dataType, DynamicVector<sns_std_suid> *suids,
186                     uint8_t minNumSuids, uint32_t maxRetries,
187                     Milliseconds retryDelay);
188 
189   /**
190    * Version of findSuidSync providing default timeout/retry behavior.
191    *
192    * @see findSuidSync
193    */
194   bool findSuidSync(const char *dataType, DynamicVector<sns_std_suid> *suids,
195                     uint8_t minNumSuids = 1) {
196     uint32_t maxRetries = (mHaveTimedOutOnSuidLookup) ? 0 : 40;
197     return findSuidSync(dataType, suids, minNumSuids, maxRetries,
198                         Milliseconds(250) /* retryDelay */);
199   }
200 
201   /**
202    * A synchronous call to obtain the attributes of the specified SUID.
203    *
204    * @param suid The SUID of the sensor
205    * @param attr A non-null pointer to the attibutes of the specified SUID that
206    *             include sensor vendor, name and max sampling rate, etc.
207    *
208    * @return true if the attribute was successfully obtained and attr populated.
209    */
210   bool getAttributesSync(const sns_std_suid& suid, SeeAttributes *attr);
211 
212   /**
213    * @return the SeeCalHelper instance used by this SeeHelper
214    */
getCalHelper()215   SeeCalHelper *getCalHelper() {
216     return mCalHelper;
217   }
218 
219   /**
220    * Initializes and waits for the sensor client service to become available,
221    * and obtains remote_proc and cal sensors' info for future operations. This
222    * function must be called first to initialize the object and be called only
223    * once.
224    *
225    * @param cbIf A pointer to the callback interface that will be invoked to
226    *             handle all async requests with callback data type defined in
227    *             the interface.
228    * @param timeout The wait timeout in microseconds.
229    * @param skipDefaultSensorInit If true, don't register remote proc status and
230    *                              calibration sensors (e.g. if another SeeHelper
231    *                              instance will manage these)
232    *
233    * @return true if all initialization steps succeeded.
234    */
235   bool init(SeeHelperCallbackInterface *cbIf,
236             Microseconds timeout = kDefaultSeeWaitTimeout,
237             bool skipDefaultSensorInit = false);
238 
239   /**
240    * Makes a sensor configuration request to SEE.
241    *
242    * @param request The sensor request to make.
243    *
244    * @return true if the request has been successfully made.
245    */
246   bool makeRequest(const SeeSensorRequest& request);
247 
248   /**
249    * Makes a sensor flush request to SEE.
250    *
251    * @param sensorType The type of sensor to request the flush.
252    *
253    * @return true if the request has been successfully made.
254    */
255   bool flush(SensorType sensorType);
256 
257   /**
258    * Register a SensorType with the SUID of the SEE sensor/driver.
259    *
260    * Only registered SUIDs will call the indication callback provided in init()
261    * with populated CHRE sensor events. Each SUID/SensorType pair can only be
262    * registered once. It's illegal to register SensorType::Unknown.
263    *
264    * If an SUID is registered with a second SensorType, another client may be
265    * created to disambiguate the SUID representation.
266    *
267    * @param sensorType The SensorType to register.
268    * @param suid The SUID of the sensor.
269    * @param resample Whether to resample this sensorType.
270    * @param prevRegistered A non-null pointer to a boolean that indicates
271    *        whether the SUID/SensorType pair has been previously registered.
272    *
273    * @return true if the SUID/SensorType pair was successfully registered.
274    */
275   bool registerSensor(SensorType sensorType, const sns_std_suid& suid,
276                       bool resample, bool *prevRegistered);
277 
278   /**
279    * Checks whether the given SensorType has been successfully registered
280    * already via registerSensor().
281    *
282    * @param sensorType The SensorType to check.
283    *
284    * @return true if the given sensor type has been registered, false otherwise
285    */
286   bool sensorIsRegistered(SensorType sensorType) const;
287 
288  protected:
289   struct SnsClientApi {
290     decltype(sns_client_init)   *sns_client_init;
291     decltype(sns_client_deinit) *sns_client_deinit;
292     decltype(sns_client_send)   *sns_client_send;
293   };
294 
295   //! Contains the API this SeeHelper instance uses to interact with SEE
296   const SnsClientApi *mSnsClientApi = &kDefaultApi;
297 
298   /**
299    * Get the cached SUID of a calibration sensor that corresponds to the
300    * specified sensorType.
301    *
302    * @param sensorType The sensor type of the calibration sensor.
303    *
304    * @return A constant reference to the calibration sensor's SUID if present.
305    *         Otherwise, a reference to sns_suid_sensor_init_zero is returned.
306    */
getCalSuidFromSensorType(SensorType sensorType)307   const sns_std_suid& getCalSuidFromSensorType(SensorType sensorType) const {
308     return mCalHelper->getCalSuidFromSensorType(sensorType);
309   }
310 
311   /**
312    * A convenience method to send a request and wait for the indication if it's
313    * a synchronous one using the default client obtained in init().
314    *
315    * @see sendReq
316    */
317   bool sendReq(
318       const sns_std_suid& suid,
319       void *syncData, const char *syncDataType,
320       uint32_t msgId, void *payload, size_t payloadLen,
321       bool batchValid, uint32_t batchPeriodUs, bool passive,
322       bool waitForIndication,
323       Nanoseconds timeoutResp = kDefaultSeeRespTimeout,
324       Nanoseconds timeoutInd = kDefaultSeeIndTimeout) {
325     return sendReq(mSeeClients[0], suid,
326                    syncData, syncDataType,
327                    msgId, payload, payloadLen,
328                    batchValid, batchPeriodUs, passive,
329                    waitForIndication,
330                    timeoutResp, timeoutInd);
331   }
332 
333  private:
334   static const SnsClientApi kDefaultApi;
335 
336   //! Used to synchronize responses and indications.
337   ConditionVariable mCond;
338 
339   //! Used with mCond, and to protect access to member variables from other
340   //! threads.
341   Mutex mMutex;
342 
343   //! Callback interface for sensor events.
344   SeeHelperCallbackInterface *mCbIf = nullptr;
345 
346   //! The list of SEE clients initiated by SeeHelper.
347   DynamicVector<sns_client *> mSeeClients;
348 
349   //! The list of SensorTypes registered and their corresponding SUID and
350   //! client.
351   DynamicVector<SensorInfo> mSensorInfos;
352 
353   //! Data struct to store sync APIs data.
354   void *mSyncData = nullptr;
355 
356   //! The data type whose indication this SeeHelper is waiting for in
357   //! findSuidSync.
358   const char *mSyncDataType = nullptr;
359 
360   //! The SUID whose indication this SeeHelper is waiting for in a sync call.
361   sns_std_suid mSyncSuid = sns_suid_sensor_init_zero;
362 
363   //! true if we are waiting on an indication for a sync call.
364   bool mWaitingOnInd = false;
365 
366   //! true if we are waiting on a response of a request.
367   bool mWaitingOnResp = false;
368 
369   //! true if we've timed out in findSuidSync at least once
370   bool mHaveTimedOutOnSuidLookup = false;
371 
372   //! The response error of the request we just made.
373   sns_std_error mRespError;
374 
375   //! A transaction ID that increments for each request.
376   uint32_t mCurrentTxnId = 0;
377 
378   //! The number of consecutive missing responses.
379   uint32_t mNumMissingResp = 0;
380 
381   //! The SUID for the remote_proc sensor.
382   Optional<sns_std_suid> mRemoteProcSuid;
383 
384   //! The SUID for the resampler sensor.
385   Optional<sns_std_suid> mResamplerSuid;
386 
387   //! Handles sensor calibration data
388   SeeCalHelper *mCalHelper;
389 
390   //! true if we own the memory to mCalHelper and should free it when done
391   bool mOwnsCalHelper;
392 
393   /**
394    * Initializes the SEE remote processor sensor and makes a data request.
395    *
396    * @return true if the remote proc sensor was successfully initialized.
397    */
398   bool initRemoteProcSensor();
399 
400   /**
401    * Initializes the SEE resampler sensor.
402    *
403    * @return true if the resampler sensor was successfully initialized.
404    */
405   bool initResamplerSensor();
406 
407   /**
408    * Sends a request to SEE and waits for the response.
409    *
410    * @param client The pointer to sns_client to make the request with.
411    * @param req A pointer to the sns_client_request_msg to be sent.
412    * @param timeoutResp How long to wait for the response before abandoning it.
413    *
414    * @return true if the request was sent and the response was received
415    *         successfully.
416    */
417   bool sendSeeReqSync(sns_client *client, sns_client_request_msg *req,
418                       Nanoseconds timeoutResp);
419 
420   /**
421    * Wrapper to send a SEE request and wait for the indication if it's a
422    * synchronous one.
423    *
424    * Only one request can be pending at a time per instance of SeeHelper.
425    *
426    * @param client The pointer to sns_client to make requests with.
427    * @param suid The SUID of the sensor the request is sent to
428    * @param syncData The data struct or container to receive a sync call's data
429    * @param syncDataType The data type we are waiting for.
430    * @param msgId Message ID of the request to send
431    * @param payload A non-null pointer to the pb-encoded message
432    * @param payloadLen The length of payload
433    * @param batchValid Whether batchPeriodUs is valid and applicable to this
434    *                   request
435    * @param batchPeriodUs The batch period in microseconds
436    * @param passive Whether this is a passive request
437    * @param waitForIndication Whether to wait for the indication of the
438    *                          specified SUID or not.
439    * @param timeoutResp How long to wait for the response before abandoning it
440    * @param timeoutInd How long to wait for the indication before abandoning it
441    *
442    * @return true if the request has been sent and the response/indication it's
443    *         waiting for has been successfully received
444    */
445   bool sendReq(
446       sns_client *client, const sns_std_suid& suid,
447       void *syncData, const char *syncDataType,
448       uint32_t msgId, void *payload, size_t payloadLen,
449       bool batchValid, uint32_t batchPeriodUs, bool passive,
450       bool waitForIndication,
451       Nanoseconds timeoutResp = kDefaultSeeRespTimeout,
452       Nanoseconds timeoutInd = kDefaultSeeIndTimeout);
453 
454   /**
455    * A helper function that prepares SeeHelper to wait for an indication.
456    *
457    * @see sendReq
458    */
459   void prepareWaitForInd(const sns_std_suid& suid, void *syncData,
460                          const char *syncDataType);
461 
462   /**
463    * A helper function that waits for the indication.
464    *
465    * @return true if the inication is received  before timeout.
466    *
467    * @see sendReq
468    */
469   bool waitForInd(bool reqSent, Nanoseconds timeoutInd);
470 
471   /**
472    * Handles the payload of a sns_client_event_msg.
473    */
474   void handleSnsClientEventMsg(
475       sns_client *client, const void *payload, size_t payloadLen);
476 
477   /**
478    * Handles a response from SEE for a request sent with the specified
479    * transaction ID.
480    */
481   void handleSeeResp(uint32_t txnId, sns_std_error error);
482 
483   /**
484    * Extracts "this" from cbData and calls through to handleSnsClientEventMsg()
485    *
486    * @see sns_client_ind
487    */
488   static void seeIndCb(sns_client *client, void *msg, uint32_t msgLen,
489                        void *cbData);
490 
491   /**
492    * Extracts "this" from cbData and calls through to handleSeeResp()
493    *
494    * @see sns_client_resp
495    */
496   static void seeRespCb(sns_client *client, sns_std_error error, void *cbData);
497 
498   /**
499    * A wrapper to initialize a sns_client.
500    *
501    * @see sns_client_init
502    */
503   bool waitForService(sns_client **client,
504                       Microseconds timeout = kDefaultSeeWaitTimeout);
505 
506   /**
507    * @return SensorInfo instance found in mSensorInfos with the given
508    *         SensorType, or nullptr if not found
509    */
510   const SensorInfo *getSensorInfo(SensorType sensorType) const;
511 };
512 
513 #ifdef CHRE_SLPI_UIMG_ENABLED
514 /**
515  * A version of SeeHelper that explicitly uses the QMI API on the bottom edge
516  * and therefore only works in big image (but goes through CM instead of QCM
517  * within SEE).
518  *
519  * @see SeeHelper
520  */
521 class BigImageSeeHelper : public SeeHelper {
522  public:
BigImageSeeHelper(SeeCalHelper * calHelper)523   BigImageSeeHelper(SeeCalHelper *calHelper) : SeeHelper(calHelper) {
524     mSnsClientApi = &kQmiApi;
525   }
526 
527  private:
528   static const SnsClientApi kQmiApi;
529 };
530 #endif  // CHRE_SLPI_UIMG_ENABLED
531 
532 }  // namespace chre
533 
534 #endif  // CHRE_PLATFORM_SLPI_SEE_SEE_HELPER_H_
535