1*61c4878aSAndroid Build Coastguard Worker.. _seed-0120: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker========================== 4*61c4878aSAndroid Build Coastguard Worker0120: Sensor Configuration 5*61c4878aSAndroid Build Coastguard Worker========================== 6*61c4878aSAndroid Build Coastguard Worker.. seed:: 7*61c4878aSAndroid Build Coastguard Worker :number: 0120 8*61c4878aSAndroid Build Coastguard Worker :name: Sensors Config 9*61c4878aSAndroid Build Coastguard Worker :status: Open for Comments 10*61c4878aSAndroid Build Coastguard Worker :proposal_date: 2023-11-28 11*61c4878aSAndroid Build Coastguard Worker :cl: 183150 12*61c4878aSAndroid Build Coastguard Worker :authors: Yuval Peress 13*61c4878aSAndroid Build Coastguard Worker :facilitator: Taylor Cramer 14*61c4878aSAndroid Build Coastguard Worker 15*61c4878aSAndroid Build Coastguard Worker------- 16*61c4878aSAndroid Build Coastguard WorkerSummary 17*61c4878aSAndroid Build Coastguard Worker------- 18*61c4878aSAndroid Build Coastguard WorkerThis SEED details the configuration aspect of both sensors and the sensor 19*61c4878aSAndroid Build Coastguard Workerframework that will reside under the ``pw_sensor`` module. Under this design, 20*61c4878aSAndroid Build Coastguard Workerboth a ``Sensor`` and a ``Connection`` object will be configurable with the same 21*61c4878aSAndroid Build Coastguard WorkerAPI. As such, the ``Configuration`` is a part of both layers for the sensor 22*61c4878aSAndroid Build Coastguard Workerstack: 23*61c4878aSAndroid Build Coastguard Worker 24*61c4878aSAndroid Build Coastguard Worker* There exists a ``Configuration`` class which holds the currently requested 25*61c4878aSAndroid Build Coastguard Worker configuration. 26*61c4878aSAndroid Build Coastguard Worker* A ``Configuration`` is owned by a ``Sensor`` in a 1:1 relationship. Each 27*61c4878aSAndroid Build Coastguard Worker sensor only supports 1 configuration. 28*61c4878aSAndroid Build Coastguard Worker* The sensor framework (a layer above the ``Sensor`` driver) has the concept of 29*61c4878aSAndroid Build Coastguard Worker a ``Connection``. You can open multiple connections to the same sensor and the 30*61c4878aSAndroid Build Coastguard Worker framework will handle the multiplexing. Each ``Connection`` owns a 31*61c4878aSAndroid Build Coastguard Worker ``Configuration`` in a similar 1:1 relationship like the ``Sensor``. The only 32*61c4878aSAndroid Build Coastguard Worker difference is that when a ``Connection``'s configuration changes, the 33*61c4878aSAndroid Build Coastguard Worker framework arbitrates the multiple ``Connection``\s to produce a single final 34*61c4878aSAndroid Build Coastguard Worker ``Configuration`` of the ``Sensor``. 35*61c4878aSAndroid Build Coastguard Worker 36*61c4878aSAndroid Build Coastguard Worker.. mermaid:: 37*61c4878aSAndroid Build Coastguard Worker :alt: Configuration relationship 38*61c4878aSAndroid Build Coastguard Worker :align: center 39*61c4878aSAndroid Build Coastguard Worker 40*61c4878aSAndroid Build Coastguard Worker classDiagram 41*61c4878aSAndroid Build Coastguard Worker class Configuration 42*61c4878aSAndroid Build Coastguard Worker class Sensor 43*61c4878aSAndroid Build Coastguard Worker class Connection 44*61c4878aSAndroid Build Coastguard Worker class SensorFramework 45*61c4878aSAndroid Build Coastguard Worker Sensor "1" *-- "1" Configuration 46*61c4878aSAndroid Build Coastguard Worker Connection "1" *-- "1" Configuration 47*61c4878aSAndroid Build Coastguard Worker SensorFramework "1" *-- "*" Sensor 48*61c4878aSAndroid Build Coastguard Worker SensorFramework "1" *-- "*" Connection 49*61c4878aSAndroid Build Coastguard Worker 50*61c4878aSAndroid Build Coastguard Worker---------- 51*61c4878aSAndroid Build Coastguard WorkerMotivation 52*61c4878aSAndroid Build Coastguard Worker---------- 53*61c4878aSAndroid Build Coastguard WorkerMaking sensor drivers configurable lends to the reusability of the driver. 54*61c4878aSAndroid Build Coastguard WorkerAdditionally, each ``Connection`` in the sensor framework should be able to 55*61c4878aSAndroid Build Coastguard Workerconvey the requested configuration of the client. As depicted above, a 56*61c4878aSAndroid Build Coastguard Worker``Connection`` will own a single ``Configuration``. Once a change is made, the 57*61c4878aSAndroid Build Coastguard Workerframework will process the change and form a union of all the ``Configuration`` 58*61c4878aSAndroid Build Coastguard Workerobjects that are pointed to the same ``Sensor``. This new union will be used as 59*61c4878aSAndroid Build Coastguard Workerthe single new configuration of the ``Sensor`` and all ``Connection``\s will be 60*61c4878aSAndroid Build Coastguard Workernotified of the change. 61*61c4878aSAndroid Build Coastguard Worker 62*61c4878aSAndroid Build Coastguard Worker------------ 63*61c4878aSAndroid Build Coastguard WorkerDesign / API 64*61c4878aSAndroid Build Coastguard Worker------------ 65*61c4878aSAndroid Build Coastguard Worker 66*61c4878aSAndroid Build Coastguard WorkerMeasurement Types 67*61c4878aSAndroid Build Coastguard Worker----------------- 68*61c4878aSAndroid Build Coastguard WorkerMeasurement types include things like *acceleration*, *rotational velocity*, 69*61c4878aSAndroid Build Coastguard Worker*magnetic field*, etc. Each type will be described by a ``uint16_t`` hash of the 70*61c4878aSAndroid Build Coastguard Workername and the unit strings each. This makes the measurement type automatically 71*61c4878aSAndroid Build Coastguard Workereasy to log in a human readable manner when leveraging tokenized logging. 72*61c4878aSAndroid Build Coastguard WorkerAdditionally, the final measurement type (being the concatination of 2 tokens) 73*61c4878aSAndroid Build Coastguard Workeris represented as a ``uint32_t``. 74*61c4878aSAndroid Build Coastguard Worker 75*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 76*61c4878aSAndroid Build Coastguard Worker 77*61c4878aSAndroid Build Coastguard Worker union MeasurementType { 78*61c4878aSAndroid Build Coastguard Worker struct { 79*61c4878aSAndroid Build Coastguard Worker uint16_t name_token; 80*61c4878aSAndroid Build Coastguard Worker uint16_t unit_token; 81*61c4878aSAndroid Build Coastguard Worker } 82*61c4878aSAndroid Build Coastguard Worker uint32_t type; 83*61c4878aSAndroid Build Coastguard Worker }; 84*61c4878aSAndroid Build Coastguard Worker 85*61c4878aSAndroid Build Coastguard Worker #define PW_SENSOR_MEASUREMENT_TYPE(domain, name_str, unit_str) \ 86*61c4878aSAndroid Build Coastguard Worker { \ 87*61c4878aSAndroid Build Coastguard Worker .name_token = \ 88*61c4878aSAndroid Build Coastguard Worker PW_TOKENIZE_STRING_MASK(domain, 0xffff, name_str), \ 89*61c4878aSAndroid Build Coastguard Worker .unit_token = \ 90*61c4878aSAndroid Build Coastguard Worker PW_TOKENIZE_STRING_MASK(domain, 0xffff, unit_str), \ 91*61c4878aSAndroid Build Coastguard Worker } 92*61c4878aSAndroid Build Coastguard Worker 93*61c4878aSAndroid Build Coastguard WorkerPigweed would include some common measurement types: 94*61c4878aSAndroid Build Coastguard Worker 95*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 96*61c4878aSAndroid Build Coastguard Worker 97*61c4878aSAndroid Build Coastguard Worker constexpr MeasurementType kAcceleration = 98*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_MEASUREMENT_TYPE("PW_SENSOR_MEASUREMENT_TYPE", "acceleration", "m/s2"); 99*61c4878aSAndroid Build Coastguard Worker constexpr MeasurementType kRotationalVelocity = 100*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_MEASUREMENT_TYPE("PW_SENSOR_MEASUREMENT_TYPE", "rotational velocity", "rad/s"); 101*61c4878aSAndroid Build Coastguard Worker constexpr MeasurementType kMagneticField = 102*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_MEASUREMENT_TYPE("PW_SENSOR_MEASUREMENT_TYPE", "magnetic field", "T"); 103*61c4878aSAndroid Build Coastguard Worker constexpr MeasurementType kStep = 104*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_MEASUREMENT_TYPE("PW_SENSOR_MEASUREMENT_TYPE", "step count", "step"); 105*61c4878aSAndroid Build Coastguard Worker 106*61c4878aSAndroid Build Coastguard WorkerApplications can add their own unique units which will not collide as long as 107*61c4878aSAndroid Build Coastguard Workerthey have a unique domain, name, or unit representation: 108*61c4878aSAndroid Build Coastguard Worker 109*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 110*61c4878aSAndroid Build Coastguard Worker 111*61c4878aSAndroid Build Coastguard Worker /// A measurement of how many pancakes something is worth. 112*61c4878aSAndroid Build Coastguard Worker constexpr MeasurementType kPancakes = 113*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_MEASUREMENT_TYPE("iHOP", "value", "pnks"); 114*61c4878aSAndroid Build Coastguard Worker 115*61c4878aSAndroid Build Coastguard WorkerAttribute Types 116*61c4878aSAndroid Build Coastguard Worker--------------- 117*61c4878aSAndroid Build Coastguard WorkerAttribute types are much simpler that ``MeasurementTypes`` since they derive 118*61c4878aSAndroid Build Coastguard Workertheir units from the measurement type. Instead, they'll just be 119*61c4878aSAndroid Build Coastguard Workerrepresented via a single token: 120*61c4878aSAndroid Build Coastguard Worker 121*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 122*61c4878aSAndroid Build Coastguard Worker 123*61c4878aSAndroid Build Coastguard Worker using AttributeType = uint32_t; 124*61c4878aSAndroid Build Coastguard Worker 125*61c4878aSAndroid Build Coastguard Worker #define PW_SENSOR_ATTRIBUTE_TYPE(domain, name_str) \ 126*61c4878aSAndroid Build Coastguard Worker PW_TOKENIZE_STRING_DOMAIN(domain, name_str) 127*61c4878aSAndroid Build Coastguard Worker 128*61c4878aSAndroid Build Coastguard WorkerSimilar to the ``MeasurementType``, Pigweed will define a few common attribute 129*61c4878aSAndroid Build Coastguard Workertypes: 130*61c4878aSAndroid Build Coastguard Worker 131*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 132*61c4878aSAndroid Build Coastguard Worker 133*61c4878aSAndroid Build Coastguard Worker constexpr AttributeType kOffset = 134*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_ATTRIBUTE_TYPE("PW_SENSOR_ATTRIBUTE_TYPE", "offset"); 135*61c4878aSAndroid Build Coastguard Worker constexpr AttributeType kFullScale = 136*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_ATTRIBUTE_TYPE("PW_SENSOR_ATTRIBUTE_TYPE", "full scale"); 137*61c4878aSAndroid Build Coastguard Worker constexpr AttributeType kSampleRate = 138*61c4878aSAndroid Build Coastguard Worker PW_SENSOR_ATTRIBUTE_TYPE("PW_SENSOR_ATTRIBUTE_TYPE", "sample rate"); 139*61c4878aSAndroid Build Coastguard Worker 140*61c4878aSAndroid Build Coastguard WorkerAttributes 141*61c4878aSAndroid Build Coastguard Worker---------- 142*61c4878aSAndroid Build Coastguard WorkerA single ``Attribute`` representation is the combination of 3 fields: 143*61c4878aSAndroid Build Coastguard Workermeasurement type, attribute type, and value. 144*61c4878aSAndroid Build Coastguard Worker 145*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 146*61c4878aSAndroid Build Coastguard Worker 147*61c4878aSAndroid Build Coastguard Worker class Attribute : public pw::IntrusiveList<Attribute>::Item { 148*61c4878aSAndroid Build Coastguard Worker public: 149*61c4878aSAndroid Build Coastguard Worker Attribute(MeasurementType measurement_type, AttributeType attribute_type) 150*61c4878aSAndroid Build Coastguard Worker : measurement_type(measurement_type), attribute_type(attribute_type) {} 151*61c4878aSAndroid Build Coastguard Worker 152*61c4878aSAndroid Build Coastguard Worker bool operator==(const Attribute& rhs) const { 153*61c4878aSAndroid Build Coastguard Worker return measurement_type == rhs.measurement_type && 154*61c4878aSAndroid Build Coastguard Worker attribute_type == rhs.attribute_type && 155*61c4878aSAndroid Build Coastguard Worker memcmp(data, rhs.data, sizeof(data)) == 0; 156*61c4878aSAndroid Build Coastguard Worker } 157*61c4878aSAndroid Build Coastguard Worker 158*61c4878aSAndroid Build Coastguard Worker Attribute& operator=(const Attribute& rhs) { 159*61c4878aSAndroid Build Coastguard Worker PW_DASSERT(measurement_type == rhs.measurement_type); 160*61c4878aSAndroid Build Coastguard Worker PW_DASSERT(attribute_type == rhs.attribute_type); 161*61c4878aSAndroid Build Coastguard Worker memcpy(data, rhs.data, sizeof(data)); 162*61c4878aSAndroid Build Coastguard Worker return *this; 163*61c4878aSAndroid Build Coastguard Worker } 164*61c4878aSAndroid Build Coastguard Worker 165*61c4878aSAndroid Build Coastguard Worker template <typename T> 166*61c4878aSAndroid Build Coastguard Worker void SetValue(typename std::enable_if<std::is_integral_v<T> || 167*61c4878aSAndroid Build Coastguard Worker std::is_floating_point_v<T>, 168*61c4878aSAndroid Build Coastguard Worker T>::type value) { 169*61c4878aSAndroid Build Coastguard Worker memcpy(data, value, sizeof(T)); 170*61c4878aSAndroid Build Coastguard Worker } 171*61c4878aSAndroid Build Coastguard Worker 172*61c4878aSAndroid Build Coastguard Worker template <typename T> 173*61c4878aSAndroid Build Coastguard Worker typename std::enable_if<std::is_integral_v<T> || 174*61c4878aSAndroid Build Coastguard Worker std::is_floating_point_v<T>, 175*61c4878aSAndroid Build Coastguard Worker T>::type GetValue() { 176*61c4878aSAndroid Build Coastguard Worker return *static_cast<T*>(data); 177*61c4878aSAndroid Build Coastguard Worker } 178*61c4878aSAndroid Build Coastguard Worker 179*61c4878aSAndroid Build Coastguard Worker MeasurementType measurement_type; 180*61c4878aSAndroid Build Coastguard Worker AttributeType attribute_type; 181*61c4878aSAndroid Build Coastguard Worker 182*61c4878aSAndroid Build Coastguard Worker private: 183*61c4878aSAndroid Build Coastguard Worker std::byte data[sizeof(long double)]; 184*61c4878aSAndroid Build Coastguard Worker }; 185*61c4878aSAndroid Build Coastguard Worker 186*61c4878aSAndroid Build Coastguard WorkerConfiguration 187*61c4878aSAndroid Build Coastguard Worker------------- 188*61c4878aSAndroid Build Coastguard WorkerA configuration is simply a list of attributes. Developers will have 2 options 189*61c4878aSAndroid Build Coastguard Workerfor accessing and manipulating configurations. The first is to create the 190*61c4878aSAndroid Build Coastguard Workersensor's desired configuration and pass it to ``Sensor::SetConfiguration()``. 191*61c4878aSAndroid Build Coastguard WorkerThe driver will return a ``Future`` using the async API and will attempt to set 192*61c4878aSAndroid Build Coastguard Workerthe desired configuration. The second option is to first query the sensor's 193*61c4878aSAndroid Build Coastguard Workerattribute values, then manipulate them, and finally set the new values using the 194*61c4878aSAndroid Build Coastguard Workersame ``Sensor::SetConfiguration()`` function. 195*61c4878aSAndroid Build Coastguard Worker 196*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 197*61c4878aSAndroid Build Coastguard Worker 198*61c4878aSAndroid Build Coastguard Worker using Configuration = pw::alloc::Vector<Attribute>; 199*61c4878aSAndroid Build Coastguard Worker 200*61c4878aSAndroid Build Coastguard Worker /// @brief A pollable future that returns a configuration 201*61c4878aSAndroid Build Coastguard Worker /// This future is used by the Configurable::GetConfiguration function. On 202*61c4878aSAndroid Build Coastguard Worker /// success, the content of Result will include the current values of the 203*61c4878aSAndroid Build Coastguard Worker /// requester Attribute objects. 204*61c4878aSAndroid Build Coastguard Worker class ConfigurationFuture { 205*61c4878aSAndroid Build Coastguard Worker public: 206*61c4878aSAndroid Build Coastguard Worker pw::async::Poll<pw::Result<Configuration*>> Poll(pw::async::Waker& waker); 207*61c4878aSAndroid Build Coastguard Worker }; 208*61c4878aSAndroid Build Coastguard Worker 209*61c4878aSAndroid Build Coastguard Worker class Configurable { 210*61c4878aSAndroid Build Coastguard Worker public: 211*61c4878aSAndroid Build Coastguard Worker /// @brief Get the current values of a configuration 212*61c4878aSAndroid Build Coastguard Worker /// The @p configuration will dictate both the measurement and attribute 213*61c4878aSAndroid Build Coastguard Worker /// types which are to be queried. The function will return a future and 214*61c4878aSAndroid Build Coastguard Worker /// begin performing any required bus transactions. Once complete, the 215*61c4878aSAndroid Build Coastguard Worker /// future will resolve and contain a pointer to the original Configuration 216*61c4878aSAndroid Build Coastguard Worker /// that was passed into the function, but the values will have been set. 217*61c4878aSAndroid Build Coastguard Worker virtual ConfigurationFuture GetConfiguration( 218*61c4878aSAndroid Build Coastguard Worker Configuration& configuration) = 0; 219*61c4878aSAndroid Build Coastguard Worker 220*61c4878aSAndroid Build Coastguard Worker /// @brief Set the values in the provided Configuration 221*61c4878aSAndroid Build Coastguard Worker /// The driver will attempt to set each attribute in @p configuration. By 222*61c4878aSAndroid Build Coastguard Worker /// default, if an attribute isn't supported or the exact value can't be 223*61c4878aSAndroid Build Coastguard Worker /// used, the driver will make a best effort by skipping the attribute in 224*61c4878aSAndroid Build Coastguard Worker /// the case that it's not supported or rounding it to the closest 225*61c4878aSAndroid Build Coastguard Worker /// reasonable value. On success, the function should mutate the attributes 226*61c4878aSAndroid Build Coastguard Worker /// to the actual values that were set. 227*61c4878aSAndroid Build Coastguard Worker /// For example: 228*61c4878aSAndroid Build Coastguard Worker /// Lets assume the driver supports a sample rate of either 12.5Hz or 229*61c4878aSAndroid Build Coastguard Worker /// 25Hz, but the caller used 20Hz. Assuming that @p allow_best_effort 230*61c4878aSAndroid Build Coastguard Worker /// was set to `true`, the driver is expected to set the sample rate to 231*61c4878aSAndroid Build Coastguard Worker /// 25Hz and update the attribute value from 20Hz to 25Hz. 232*61c4878aSAndroid Build Coastguard Worker virtual ConfigurationFuture SetConfiguration( 233*61c4878aSAndroid Build Coastguard Worker Configuration& configuration, bool allow_best_effort = true) = 0; 234*61c4878aSAndroid Build Coastguard Worker }; 235*61c4878aSAndroid Build Coastguard Worker 236*61c4878aSAndroid Build Coastguard WorkerMemory management 237*61c4878aSAndroid Build Coastguard Worker----------------- 238*61c4878aSAndroid Build Coastguard WorkerIn the ``Configurable`` interface we expose 2 functions which allow getting and 239*61c4878aSAndroid Build Coastguard Workersetting the configuration via the Pigweed async API. In both cases, the caller 240*61c4878aSAndroid Build Coastguard Workerowns the memory of the configuration. It is the caller that is required to 241*61c4878aSAndroid Build Coastguard Workerallocate the space of the attributes which they'd like to query or mutate and it 242*61c4878aSAndroid Build Coastguard Workeris the caller's responsibility to make sure that those attributes (via the 243*61c4878aSAndroid Build Coastguard Worker``Configuration``) do not go out of scope. The future, will not own the 244*61c4878aSAndroid Build Coastguard Workerconfiguration once the call is made, but will hold a pointer to it. This means 245*61c4878aSAndroid Build Coastguard Workerthat the address must also be stable. If the future goes out of scope, then the 246*61c4878aSAndroid Build Coastguard Workerrequest is assumed canceled, but the memory for the configuration is not 247*61c4878aSAndroid Build Coastguard Workerreleased since the future does not own the memory. 248*61c4878aSAndroid Build Coastguard Worker 249*61c4878aSAndroid Build Coastguard WorkerWhile it's possible to optimize this path a bit further, sensors are generally 250*61c4878aSAndroid Build Coastguard Workernot re-configured often. The majority of sensors force some down time and the 251*61c4878aSAndroid Build Coastguard Workerloss of some samples while being re-configured. This makes the storage and 252*61c4878aSAndroid Build Coastguard Workermutation of a ``Configuration`` less critical. It would be possible to leverage 253*61c4878aSAndroid Build Coastguard Workera ``FlatMap`` for the ``Configuration`` in order to improve the lookup time. 254*61c4878aSAndroid Build Coastguard WorkerThe biggest drawback to this approach is the lack of dynamic attribute support. 255*61c4878aSAndroid Build Coastguard WorkerIf we want to allow pluggable sensors where attributes are discovered at 256*61c4878aSAndroid Build Coastguard Workerruntime, we would not be able to leverage the ``FlatMap``. 257*61c4878aSAndroid Build Coastguard Worker 258*61c4878aSAndroid Build Coastguard WorkerAlternatively, if a ``Configuration``'s keys are known at compile time, we 259*61c4878aSAndroid Build Coastguard Workercould support the following cases: 260*61c4878aSAndroid Build Coastguard Worker 261*61c4878aSAndroid Build Coastguard Worker* When a ``Sensor`` knows which attributes it supports at compile time, we 262*61c4878aSAndroid Build Coastguard Worker should be able to allocate an appropriate ``FlatMap``. When the developer 263*61c4878aSAndroid Build Coastguard Worker requests the full configuration, we would copy that ``FlatMap`` out and allow 264*61c4878aSAndroid Build Coastguard Worker the consumer to mutate the copy. 265*61c4878aSAndroid Build Coastguard Worker* A consumer which only cares about a subset of statically known attributes, can 266*61c4878aSAndroid Build Coastguard Worker allocate their own ``FlatMap`` backed ``Configuration``. It would pass a 267*61c4878aSAndroid Build Coastguard Worker reference to this object when querying the ``Sensor`` and have the values 268*61c4878aSAndroid Build Coastguard Worker copied out into the owned ``Configuration``. 269*61c4878aSAndroid Build Coastguard Worker 270*61c4878aSAndroid Build Coastguard Worker-------------------- 271*61c4878aSAndroid Build Coastguard WorkerSensor vs. Framework 272*61c4878aSAndroid Build Coastguard Worker-------------------- 273*61c4878aSAndroid Build Coastguard WorkerWhen complete, both the ``Sensor`` and the ``Connection`` [1]_ objects will 274*61c4878aSAndroid Build Coastguard Workerinherit from the ``Configurable`` interface. The main differences are that in 275*61c4878aSAndroid Build Coastguard Workerthe case of the ``Sensor``, the configuration is assumed to be applied directly 276*61c4878aSAndroid Build Coastguard Workerto the driver, while in the case of the ``Connection``, the sensor framework 277*61c4878aSAndroid Build Coastguard Workerwill need to take into account the configurations of other ``Connection`` 278*61c4878aSAndroid Build Coastguard Workerobjects pointing to the same ``Sensor``. 279*61c4878aSAndroid Build Coastguard Worker 280*61c4878aSAndroid Build Coastguard Worker.. [1] A connection is allocated by the sensor framework to the client and 281*61c4878aSAndroid Build Coastguard Worker allows clients to request configuration changes. 282