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