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 "chre/core/sensor_type.h" 27 #include "chre/platform/condition_variable.h" 28 #include "chre/platform/mutex.h" 29 #include "chre/platform/slpi/see/see_helper_internal.h" 30 #include "chre/util/dynamic_vector.h" 31 #include "chre/util/non_copyable.h" 32 #include "chre/util/time.h" 33 #include "chre/util/unique_ptr.h" 34 35 namespace chre { 36 37 inline bool suidsMatch(const sns_std_suid& suid0, const sns_std_suid& suid1) { 38 return (suid0.suid_high == suid1.suid_high 39 && suid0.suid_low == suid1.suid_low); 40 } 41 42 //! A callback interface for receiving SeeHelper data events. 43 class SeeHelperCallbackInterface { 44 public: 45 struct SamplingStatusData { 46 SensorType sensorType; 47 struct chreSensorSamplingStatus status; 48 bool enabledValid; 49 bool intervalValid; 50 bool latencyValid; 51 }; 52 53 virtual ~SeeHelperCallbackInterface() {} 54 55 //! Invoked by the SEE thread to update sampling status. 56 virtual void onSamplingStatusUpdate( 57 UniquePtr<SamplingStatusData>&& status) = 0; 58 59 //! Invoked by the SEE thread to provide sensor data events. The event data 60 //! format is one of the chreSensorXXXData defined in the CHRE API, implicitly 61 //! specified by sensorType. 62 virtual void onSensorDataEvent( 63 SensorType sensorType, UniquePtr<uint8_t>&& eventData) = 0; 64 65 //! Invoked by the SEE thread to update the AP wake/suspend status. 66 virtual void onHostWakeSuspendEvent(bool apAwake) = 0; 67 }; 68 69 //! Default timeout for waitForService. Have a longer timeout since there may be 70 //! external dependencies blocking SEE initialization. 71 constexpr Nanoseconds kDefaultSeeWaitTimeout = Seconds(5); 72 73 //! Default timeout for sendReq response 74 constexpr Nanoseconds kDefaultSeeRespTimeout = Seconds(1); 75 76 //! Default timeout for sendReq indication 77 constexpr Nanoseconds kDefaultSeeIndTimeout = Seconds(2); 78 79 //! Length of the char array to store sensor string attributes. 80 constexpr size_t kSeeAttrStrValLen = 64; 81 82 //! A struct to facilitate getAttributesSync(). 83 struct SeeAttributes { 84 char vendor[kSeeAttrStrValLen]; 85 char name[kSeeAttrStrValLen]; 86 char type[kSeeAttrStrValLen]; 87 int64_t hwId; 88 float maxSampleRate; 89 uint8_t streamType; 90 bool passiveRequest; 91 }; 92 93 //! A struct to facilitate making sensor request 94 struct SeeSensorRequest { 95 SensorType sensorType; 96 bool enable; 97 bool passive; 98 float samplingRateHz; 99 uint32_t batchPeriodUs; 100 }; 101 102 /** 103 * A helper class for making requests to Qualcomm's Sensors Execution 104 * Environment (SEE) via the sns_client API and waiting for the response and the 105 * corresponding indication message if applicable. 106 * Not safe to use from multiple threads. Only one synchronous request can be 107 * made at a time. 108 */ 109 class SeeHelper : public NonCopyable { 110 public: 111 //! A struct to facilitate mapping between 'SUID + sns_client' and 112 //! SensorType. 113 struct SensorInfo { 114 sns_std_suid suid; 115 SensorType sensorType; 116 sns_client *client; 117 }; 118 119 /** 120 * Deinits clients before destructing this object. 121 */ 122 ~SeeHelper(); 123 124 /** 125 * A synchronous call to discover SUID(s) that supports the specified data 126 * type. This API will clear the provided dynamic vector before populating it. 127 * 128 * @param dataType A data type string, "accel" for example. 129 * @param suids A non-null pointer to a list of sensor UIDs that support the 130 * specified data type. 131 * @param minNumSuids The minimum number of SUIDs it needs to find before 132 * returning true. Otherwise, it'll re-try internally 133 * until it times out. It's illegal to set it to 0. 134 * @param maxRetries Maximum amount of times to retry looking up the SUID 135 * until giving up. 136 * @param retryDelay Time delay between retry attempts (msec). 137 * 138 * @return true if at least minNumSuids were successfully found 139 */ 140 bool findSuidSync(const char *dataType, DynamicVector<sns_std_suid> *suids, 141 uint8_t minNumSuids, uint32_t maxRetries, 142 Milliseconds retryDelay); 143 144 /** 145 * Version of findSuidSync providing default timeout/retry behavior. 146 * 147 * @see findSuidSync 148 */ 149 bool findSuidSync(const char *dataType, DynamicVector<sns_std_suid> *suids, 150 uint8_t minNumSuids = 1) { 151 uint32_t maxRetries = (mHaveTimedOutOnSuidLookup) ? 0 : 40; 152 return findSuidSync(dataType, suids, minNumSuids, maxRetries, 153 Milliseconds(250) /* retryDelay */); 154 } 155 156 /** 157 * A synchronous call to obtain the attributes of the specified SUID. 158 * 159 * @param suid The SUID of the sensor 160 * @param attr A non-null pointer to the attibutes of the specified SUID that 161 * include sensor vendor, name and max sampling rate, etc. 162 * 163 * @return true if the attribute was successfully obtained and attr populated. 164 */ 165 bool getAttributesSync(const sns_std_suid& suid, SeeAttributes *attr); 166 167 /** 168 * Initializes and waits for the sensor client service to become available, 169 * and obtains remote_proc and cal sensors' info for future operations. This 170 * function must be called first to initialize the object and be called only 171 * once. 172 * 173 * @param cbIf A pointer to the callback interface that will be invoked to 174 * handle all async requests with callback data type defined in 175 * the interface. 176 * @param timeout The wait timeout in microseconds. 177 * 178 * @return true if all initialization steps succeeded. 179 */ 180 bool init(SeeHelperCallbackInterface *cbIf, 181 Microseconds timeout = kDefaultSeeWaitTimeout); 182 183 /** 184 * Makes a sensor request to SEE. 185 * 186 * @param request The sensor request to make. 187 * 188 * @return true if the request has been successfully made. 189 */ 190 bool makeRequest(const SeeSensorRequest& request); 191 192 /** 193 * Register a SensorType with the SUID of the SEE sensor/driver. 194 * 195 * Only registered SUIDs will call the indication callback provided in init() 196 * with populated CHRE sensor events. Each SUID/SensorType pair can only be 197 * registered once. It's illegal to register SensorType::Unknown. 198 * 199 * If an SUID is registered with a second SensorType, another client may be 200 * created to disambiguate the SUID representation. 201 * 202 * @param sensorType The SensorType to register. 203 * @param suid The SUID of the sensor. 204 * @param prevRegistered A non-null pointer to a boolean that indicates 205 * whether the SUID/SensorType pair has been previously registered. 206 * 207 * @return true if the SUID/SensorType pair was successfully registered. 208 */ 209 bool registerSensor(SensorType sensorType, const sns_std_suid& suid, 210 bool *prevRegistered); 211 212 /** 213 * Checks whether the given SensorType has been successfully registered 214 * already via registerSensor(). 215 * 216 * @param sensorType The SensorType to check. 217 * 218 * @return true if the given sensor type has been registered, false otherwise 219 */ 220 bool sensorIsRegistered(SensorType sensorType) const; 221 222 protected: 223 struct SnsClientApi { 224 decltype(sns_client_init) *sns_client_init; 225 decltype(sns_client_deinit) *sns_client_deinit; 226 decltype(sns_client_send) *sns_client_send; 227 }; 228 229 /** 230 * Get the cached SUID of a calibration sensor that corresponds to the 231 * specified sensorType. 232 * 233 * @param sensorType The sensor type of the calibration sensor. 234 * 235 * @return A constant reference to the calibration sensor's SUID if present. 236 * Otherwise, a reference to sns_suid_sensor_init_zero is returned. 237 */ 238 const sns_std_suid& getCalSuidFromSensorType(SensorType sensorType) const; 239 240 /** 241 * A convenience method to send a request and wait for the indication if it's 242 * a synchronous one using the default client obtained in init(). 243 * 244 * @see sendReq 245 */ 246 bool sendReq( 247 const sns_std_suid& suid, 248 void *syncData, const char *syncDataType, 249 uint32_t msgId, void *payload, size_t payloadLen, 250 bool batchValid, uint32_t batchPeriodUs, bool passive, 251 bool waitForIndication, 252 Nanoseconds timeoutResp = kDefaultSeeRespTimeout, 253 Nanoseconds timeoutInd = kDefaultSeeIndTimeout) { 254 return sendReq(mSeeClients[0], suid, 255 syncData, syncDataType, 256 msgId, payload, payloadLen, 257 batchValid, batchPeriodUs, passive, 258 waitForIndication, 259 timeoutResp, timeoutInd); 260 } 261 262 void setSnsClientApi(const SnsClientApi *api) { 263 mSnsClientApi = api; 264 } 265 266 private: 267 static const SnsClientApi kDefaultApi; 268 269 //! Used to synchronize responses and indications. 270 ConditionVariable mCond; 271 272 //! Used with mCond, and to protect access to member variables from other 273 //! threads. 274 Mutex mMutex; 275 276 //! Callback interface for sensor events. 277 SeeHelperCallbackInterface *mCbIf = nullptr; 278 279 //! The list of SEE clients initiated by SeeHelper. 280 DynamicVector<sns_client *> mSeeClients; 281 282 //! The list of SensorTypes registered and their corresponding SUID and 283 //! client. 284 DynamicVector<SensorInfo> mSensorInfos; 285 286 //! Data struct to store sync APIs data. 287 void *mSyncData = nullptr; 288 289 //! The data type whose indication this SeeHelper is waiting for in 290 //! findSuidSync. 291 const char *mSyncDataType = nullptr; 292 293 //! The SUID whose indication this SeeHelper is waiting for in a sync call. 294 sns_std_suid mSyncSuid = sns_suid_sensor_init_zero; 295 296 //! true if we are waiting on an indication for a sync call. 297 bool mWaitingOnInd = false; 298 299 //! true if we are waiting on a response of a request. 300 bool mWaitingOnResp = false; 301 302 //! true if we've timed out in findSuidSync at least once 303 bool mHaveTimedOutOnSuidLookup = false; 304 305 //! The response error of the request we just made. 306 sns_std_error mRespError; 307 308 //! A transaction ID that increments for each request. 309 uint32_t mCurrentTxnId = 0; 310 311 //! The SUID for the remote_proc sensor. 312 Optional<sns_std_suid> mRemoteProcSuid; 313 314 //! Cal info of all the cal sensors. 315 SeeCalInfo mCalInfo[kNumSeeCalSensors]; 316 317 //! Contains the API this SeeHelper instance uses to interact with SEE 318 const SnsClientApi *mSnsClientApi = &kDefaultApi; 319 320 /** 321 * Initializes SEE calibration sensors and makes data request. 322 * 323 * @return true if cal sensor have been succcessfully initialized. 324 */ 325 bool initCalSensors(); 326 327 /** 328 * Initializes the SEE remote processor sensor and makes a data request. 329 * 330 * @return true if the remote proc sensor was successfully initialized. 331 */ 332 bool initRemoteProcSensor(); 333 334 /** 335 * Sends a request to SEE and waits for the response. 336 * 337 * @param client The pointer to sns_client to make the request with. 338 * @param req A pointer to the sns_client_request_msg to be sent. 339 * @param timeoutResp How long to wait for the response before abandoning it. 340 * 341 * @return true if the request was sent and the response was received 342 * successfully. 343 */ 344 bool sendSeeReqSync(sns_client *client, sns_client_request_msg *req, 345 Nanoseconds timeoutResp); 346 347 /** 348 * Wrapper to send a SEE request and wait for the indication if it's a 349 * synchronous one. 350 * 351 * Only one request can be pending at a time per instance of SeeHelper. 352 * 353 * @param client The pointer to sns_client to make requests with. 354 * @param suid The SUID of the sensor the request is sent to 355 * @param syncData The data struct or container to receive a sync call's data 356 * @param syncDataType The data type we are waiting for. 357 * @param msgId Message ID of the request to send 358 * @param payload A non-null pointer to the pb-encoded message 359 * @param payloadLen The length of payload 360 * @param batchValid Whether batchPeriodUs is valid and applicable to this 361 * request 362 * @param batchPeriodUs The batch period in microseconds 363 * @param passive Whether this is a passive request 364 * @param waitForIndication Whether to wait for the indication of the 365 * specified SUID or not. 366 * @param timeoutResp How long to wait for the response before abandoning it 367 * @param timeoutInd How long to wait for the indication before abandoning it 368 * 369 * @return true if the request has been sent and the response/indication it's 370 * waiting for has been successfully received 371 */ 372 bool sendReq( 373 sns_client *client, const sns_std_suid& suid, 374 void *syncData, const char *syncDataType, 375 uint32_t msgId, void *payload, size_t payloadLen, 376 bool batchValid, uint32_t batchPeriodUs, bool passive, 377 bool waitForIndication, 378 Nanoseconds timeoutResp = kDefaultSeeRespTimeout, 379 Nanoseconds timeoutInd = kDefaultSeeIndTimeout); 380 381 /** 382 * A helper function that prepares SeeHelper to wait for an indication. 383 * 384 * @see sendReq 385 */ 386 void prepareWaitForInd(const sns_std_suid& suid, void *syncData, 387 const char *syncDataType); 388 389 /** 390 * A helper function that waits for the indication. 391 * 392 * @return true if the inication is received before timeout. 393 * 394 * @see sendReq 395 */ 396 bool waitForInd(bool reqSent, Nanoseconds timeoutInd); 397 398 /** 399 * Handles the payload of a sns_client_event_msg. 400 */ 401 void handleSnsClientEventMsg( 402 sns_client *client, const void *payload, size_t payloadLen); 403 404 /** 405 * Handles a response from SEE for a request sent with the specified 406 * transaction ID. 407 */ 408 void handleSeeResp(uint32_t txnId, sns_std_error error); 409 410 /** 411 * Extracts "this" from cbData and calls through to handleSnsClientEventMsg() 412 * 413 * @see sns_client_ind 414 */ 415 static void seeIndCb(sns_client *client, void *msg, uint32_t msgLen, 416 void *cbData); 417 418 /** 419 * Extracts "this" from cbData and calls through to handleSeeResp() 420 * 421 * @see sns_client_resp 422 */ 423 static void seeRespCb(sns_client *client, sns_std_error error, void *cbData); 424 425 /** 426 * A wrapper to initialize a sns_client. 427 * 428 * @see sns_client_init 429 */ 430 bool waitForService(sns_client **client, 431 Microseconds timeout = kDefaultSeeWaitTimeout); 432 433 /** 434 * Obtains the pointer to cal data by SUID. 435 */ 436 SeeCalData *getCalDataFromSuid(const sns_std_suid& suid); 437 438 /** 439 * @return SensorInfo instance found in mSensorInfos with the given 440 * SensorType, or nullptr if not found 441 */ 442 const SensorInfo *getSensorInfo(SensorType sensorType) const; 443 }; 444 445 } // namespace chre 446 447 #endif // CHRE_PLATFORM_SLPI_SEE_SEE_HELPER_H_ 448