Home | History | Annotate | Download | only in see
      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