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