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(30);
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    * A convenience method to send a request and wait for the indication if it's
300    * a synchronous one using the default client obtained in init().
301    *
302    * @see sendReq
303    */
304   bool sendReq(
305       const sns_std_suid& suid,
306       void *syncData, const char *syncDataType,
307       uint32_t msgId, void *payload, size_t payloadLen,
308       bool batchValid, uint32_t batchPeriodUs, bool passive,
309       bool waitForIndication,
310       Nanoseconds timeoutResp = kDefaultSeeRespTimeout,
311       Nanoseconds timeoutInd = kDefaultSeeIndTimeout) {
312     return sendReq(mSeeClients[0], suid,
313                    syncData, syncDataType,
314                    msgId, payload, payloadLen,
315                    batchValid, batchPeriodUs, passive,
316                    waitForIndication,
317                    timeoutResp, timeoutInd);
318   }
319 
320  private:
321   static const SnsClientApi kDefaultApi;
322 
323   //! Used to synchronize responses and indications.
324   ConditionVariable mCond;
325 
326   //! Used with mCond, and to protect access to member variables from other
327   //! threads.
328   Mutex mMutex;
329 
330   //! Callback interface for sensor events.
331   SeeHelperCallbackInterface *mCbIf = nullptr;
332 
333   //! The list of SEE clients initiated by SeeHelper.
334   DynamicVector<sns_client *> mSeeClients;
335 
336   //! The list of SensorTypes registered and their corresponding SUID and
337   //! client.
338   DynamicVector<SensorInfo> mSensorInfos;
339 
340   //! Data struct to store sync APIs data.
341   void *mSyncData = nullptr;
342 
343   //! The data type whose indication this SeeHelper is waiting for in
344   //! findSuidSync.
345   const char *mSyncDataType = nullptr;
346 
347   //! The SUID whose indication this SeeHelper is waiting for in a sync call.
348   sns_std_suid mSyncSuid = sns_suid_sensor_init_zero;
349 
350   //! true if we are waiting on an indication for a sync call.
351   bool mWaitingOnInd = false;
352 
353   //! true if we are waiting on a response of a request.
354   bool mWaitingOnResp = false;
355 
356   //! true if we've timed out in findSuidSync at least once
357   bool mHaveTimedOutOnSuidLookup = false;
358 
359   //! The response error of the request we just made.
360   sns_std_error mRespError;
361 
362   //! A transaction ID that increments for each request.
363   uint32_t mCurrentTxnId = 0;
364 
365   //! The number of consecutive missing responses.
366   uint32_t mNumMissingResp = 0;
367 
368   //! The SUID for the remote_proc sensor.
369   Optional<sns_std_suid> mRemoteProcSuid;
370 
371   //! The SUID for the resampler sensor.
372   Optional<sns_std_suid> mResamplerSuid;
373 
374   //! Handles sensor calibration data
375   SeeCalHelper *mCalHelper;
376 
377   //! true if we own the memory to mCalHelper and should free it when done
378   bool mOwnsCalHelper;
379 
380   /**
381    * Initializes the SEE remote processor sensor and makes a data request.
382    *
383    * @return true if the remote proc sensor was successfully initialized.
384    */
385   bool initRemoteProcSensor();
386 
387   /**
388    * Initializes the SEE resampler sensor.
389    *
390    * @return true if the resampler sensor was successfully initialized.
391    */
392   bool initResamplerSensor();
393 
394   /**
395    * Sends a request to SEE and waits for the response.
396    *
397    * @param client The pointer to sns_client to make the request with.
398    * @param req A pointer to the sns_client_request_msg to be sent.
399    * @param timeoutResp How long to wait for the response before abandoning it.
400    *
401    * @return true if the request was sent and the response was received
402    *         successfully.
403    */
404   bool sendSeeReqSync(sns_client *client, sns_client_request_msg *req,
405                       Nanoseconds timeoutResp);
406 
407   /**
408    * Wrapper to send a SEE request and wait for the indication if it's a
409    * synchronous one.
410    *
411    * Only one request can be pending at a time per instance of SeeHelper.
412    *
413    * @param client The pointer to sns_client to make requests with.
414    * @param suid The SUID of the sensor the request is sent to
415    * @param syncData The data struct or container to receive a sync call's data
416    * @param syncDataType The data type we are waiting for.
417    * @param msgId Message ID of the request to send
418    * @param payload A non-null pointer to the pb-encoded message
419    * @param payloadLen The length of payload
420    * @param batchValid Whether batchPeriodUs is valid and applicable to this
421    *                   request
422    * @param batchPeriodUs The batch period in microseconds
423    * @param passive Whether this is a passive request
424    * @param waitForIndication Whether to wait for the indication of the
425    *                          specified SUID or not.
426    * @param timeoutResp How long to wait for the response before abandoning it
427    * @param timeoutInd How long to wait for the indication before abandoning it
428    *
429    * @return true if the request has been sent and the response/indication it's
430    *         waiting for has been successfully received
431    */
432   bool sendReq(
433       sns_client *client, const sns_std_suid& suid,
434       void *syncData, const char *syncDataType,
435       uint32_t msgId, void *payload, size_t payloadLen,
436       bool batchValid, uint32_t batchPeriodUs, bool passive,
437       bool waitForIndication,
438       Nanoseconds timeoutResp = kDefaultSeeRespTimeout,
439       Nanoseconds timeoutInd = kDefaultSeeIndTimeout);
440 
441   /**
442    * A helper function that prepares SeeHelper to wait for an indication.
443    *
444    * @see sendReq
445    */
446   void prepareWaitForInd(const sns_std_suid& suid, void *syncData,
447                          const char *syncDataType);
448 
449   /**
450    * A helper function that waits for the indication.
451    *
452    * @return true if the inication is received  before timeout.
453    *
454    * @see sendReq
455    */
456   bool waitForInd(bool reqSent, Nanoseconds timeoutInd);
457 
458   /**
459    * Handles the payload of a sns_client_event_msg.
460    */
461   void handleSnsClientEventMsg(
462       sns_client *client, const void *payload, size_t payloadLen);
463 
464   /**
465    * Handles a response from SEE for a request sent with the specified
466    * transaction ID.
467    */
468   void handleSeeResp(uint32_t txnId, sns_std_error error);
469 
470   /**
471    * Extracts "this" from cbData and calls through to handleSnsClientEventMsg()
472    *
473    * @see sns_client_ind
474    */
475   static void seeIndCb(sns_client *client, void *msg, uint32_t msgLen,
476                        void *cbData);
477 
478   /**
479    * Extracts "this" from cbData and calls through to handleSeeResp()
480    *
481    * @see sns_client_resp
482    */
483   static void seeRespCb(sns_client *client, sns_std_error error, void *cbData);
484 
485   /**
486    * A wrapper to initialize a sns_client.
487    *
488    * @see sns_client_init
489    */
490   bool waitForService(sns_client **client,
491                       Microseconds timeout = kDefaultSeeWaitTimeout);
492 
493   /**
494    * @return SensorInfo instance found in mSensorInfos with the given
495    *         SensorType, or nullptr if not found
496    */
497   const SensorInfo *getSensorInfo(SensorType sensorType) const;
498 };
499 
500 #ifdef CHRE_SLPI_UIMG_ENABLED
501 /**
502  * A version of SeeHelper that explicitly uses the QMI API on the bottom edge
503  * and therefore only works in big image (but goes through CM instead of QCM
504  * within SEE).
505  *
506  * @see SeeHelper
507  */
508 class BigImageSeeHelper : public SeeHelper {
509  public:
BigImageSeeHelper(SeeCalHelper * calHelper)510   BigImageSeeHelper(SeeCalHelper *calHelper) : SeeHelper(calHelper) {
511     mSnsClientApi = &kQmiApi;
512   }
513 
514  private:
515   static const SnsClientApi kQmiApi;
516 };
517 #endif  // CHRE_SLPI_UIMG_ENABLED
518 
519 }  // namespace chre
520 
521 #endif  // CHRE_PLATFORM_SLPI_SEE_SEE_HELPER_H_
522