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