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