xref: /aosp_15_r20/external/pigweed/seed/0120.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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