1## Power Management
2
3### Overview
4
5Power management (PM) is an event-driven state machine, tickled by various
6`bta/sys` events via a callback. The actual state switching calls are handled
7by the BTM HCI interfacing code, with results being posted back to the PM
8code via the BTA workqueue thread.
9
10Power states are managed per-device, per-profile, so every incoming event
11includes a profile ID, app ID, and a `BD_ADDR`.
12
13The events fired to drive the state machine at the time of this writing are:
14
15  - `BTA_SYS_CONN_OPEN`
16  - `BTA_SYS_CONN_CLOSE`
17  - `BTA_SYS_CONN_IDLE`
18  - `BTA_SYS_CONN_BUSY`
19  - `BTA_SYS_APP_OPEN`
20  - `BTA_SYS_APP_CLOSE`
21  - `BTA_SYS_SCO_OPEN`
22  - `BTA_SYS_SCO_CLOSE`
23
24Each of these correspond to a function name in `bta/sys/bta_sys_conn.cc`, which
25are called by each profile definition in `bta/$PROFILE`.
26
27The PM code makes calls into the BTM module to set various power
28states. Responses are handled in an asynchronous fashion, primarily via the
29callbacks `bta_dm_pm_cback` and `bta_dm_pm_timer_cback`. Responses are handled
30through the BTA workqueue thread and the `bta_dm_pm_btm_status` function. Since
31we might possibly get into a bad state where we never hear back from the
32controller, timers are used to post messages to the BTA workqueue thread as
33well, which filters down through the same status function.
34
35Overall power states are managed *per device*, not per connection, but the power
36policy is determined by the greatest allowable power action defined across all
37currently known connections to a given device. Thus, if RFCOMM specifies that
38it's willing to go to into SNIFF and specifies that as an action, and say, a PAN
39connection is up which specifies it is willing to go into SNIFF, but its action
40states it wants ACTIVE, the power management code will change to ACTIVE.
41
42### Power management tables
43
44The tables that determine which power levels are acceptable for which profiles
45and what actions to take for the above events are defined in the
46`bta/dm/bta_dm_cfg.cc` file, as `bta_dm_pm_cfg`, `bta_dm_pm_spec`, and
47`bta_dm_ssr_spec`.
48
49During a lookup attempt, the code iterates over the `bta_dm_pm_cfg` array,
50looking for a match between the profile and app IDs. When it finds one, it uses
51the `spec_idx` field to index into `bta_dm_pm_spec` array to determine which
52power modes are acceptable and what actions to take for each event.
53
54The action constants are defined in `bta_api.h` and are defined as a series of
55hex bitfields. The actual actions taken are determined by the
56`bta_dm_pm_set_mode` function, but a few of the actions listed deserve some
57additional description:
58
59  - `BTA_DM_PM_NO_ACTION` is effectively a no-op and has a value of zero, so any
60    other profile will override this.
61  - `BTA_DM_PM_NO_PREF` overrides `BTA_DM_PM_NO_ACTION` and if selected as the
62    action that `bta_dm_pm_set_mode` will take, the connection will be removed
63    from `bta_dm_conn_srvcs` and no longer be considered for power management
64    decisions.
65  - `BTA_DM_PM_SNIFF` through `BTA_DM_PM_SNIFF4` are special, in that each
66    level specifies a set of parameters for the SNIFF mode which relate to the
67    min and max intervals, the number of attempts and the timeout. The overall
68    action is still the same, however -- SNIFF mode is attempted. There are
69    definitions available up to SNIFF7, but actual SSR values are only defined
70    up to SNIFF4. Params are defined in `bta_dm_ssr_spec`.
71  - `BTA_DM_PM_ACTIVE` is full-on power.
72  - `BTA_DM_PM_RETRY` has the same effect as `BTA_DM_PM_NO_ACTION`, except a
73    timeout is possible to be set, which effectively allows a power operation to
74    be "retried".
75
76### Initialization
77
78`bta_dm_pm.cc`'s `bta_dm_init_pm` function calls out to register
79`bta_dm_pm_cback` with the bta sys module for incoming power management events,
80and also registers `bta_dm_pm_btm_cback` with the btm module to handle responses
81and timeouts of HCI requests (via `bta_dm_pm_btm_status`).
82
83At this point, the power managment code is basically done until the first set of
84events come in through `bta_dm_pm_cback`.
85
86Throughout the `bta_dm_pm.cc` file, connections whose power management states are
87managed are tracked in a global array called `bta_dm_conn_srvcs`. Unfortunately,
88while this variable is declared as an extern in the `bta_dm_int.h` file, it only
89seems to be used in the `bta_dm_act.cc` file, and only for reinitialization.
90
91### Event flow
92
93#### Events fired from SYS
94
95  1. An event is fired from one of the methods mentioned above in
96     `bta/sys/bta_sys_conn.cc`
97  2. The `bta_dm_pm_cback` function is called.
98     - The power mode config is looked up in the `bta_dm_pm_cfg` table. If none
99       are found for the given profile ID and app ID, the function simply
100       returns with no action taken.
101     - If any timers were set for the given `BD_ADDR`, they are stopped.
102     - The SSR params for the CONN_OPEN event are looked up.
103     - The power spec state table (`bta_dm_pm_spec`) is checked to see if
104       there's no action to be performed (`BTA_DM_PM_NO_ACTION`), and if so,
105       returns with no action taken.
106     - `bta_dm_conn_srvcs` is consulted to ensure there's an entry for this
107       connection if it's supposed to be managed according to the power spec
108       state tables. If the spec specifies `BTA_DM_PM_NO_PREF`, then any
109       existing entry in this list is removed, otherwise one is added/updated
110       with the state given to the function.
111  3. `bta_dm_pm_cback` checks to see if the `bta_dm_ssr_spec` specifies SSR
112     adjustments are to be made, and if so, `bta_dm_pm_ssr` is called with the
113     peer `BD_ADDR`.
114     - `bta_dm_pm_ssr` iterates the managed services array to find all connected
115       services for the given `BD_ADDR`, then looks up the ssr values from the
116       `bta_dm_ssr_spec` tables, looking for the smallest max latency to use.
117     - `bta_dm_pm_ssr` calls `BTM_SetSsrParams` to actually send along the SSR
118       params to the bluetooth chip.
119  4. `bta_dm_pm_cback` calls `bta_dm_pm_set_mode` with the peer address and the
120     `timed_out` parameter set to `false`.
121     - For each managed connection, `bta_dm_pm_set_mode` grabs
122       both actions specified for the profile in the `bta_dm_pm_spec` tables. If
123       the first power management action didn't timeout (or was never attempted,
124       according to the `tBTA_DM_PEER_DEVICE` `pm_mode_failed` and
125       `pm_mode_attempted` fields), its timeout and mode are used. Otherwise,
126       the same check is done against the second action and it is used
127       instead. If both actions have been attempted, then the action is set to
128       `BTA_DM_PM_NO_ACTION`. Only the highest power mode action is chosen from
129       all connected profiles.
130     - If the chosen action is `BTA_DM_PM_PARK` or `BTA_DM_PM_SNIFF` but the
131       profile doesn't allow it, this function takes no action.
132     - If a timeout is specified in the power spec table, then an unused timer
133       in `bta_dm_cb.pm_timer` is started.
134     - If the action chosen is `BTA_DM_PM_PARK`, `bta_dm_pm_park` is called,
135       which calls `BTM_ReadPowerMode` and `BTM_SetPowerMode` to make an HCI
136       request to enable PARK for the given peer and connection.
137     - If the action chosen is `BTA_DM_PM_SNIFF`, the peer device's link policy
138       is checked to see if it's allowed. If so, then `bta_dm_pm_sniff` is
139       called, which makes various calls to `BTM_ReadLocalFeatures`,
140       `BTM_ReadRemoteFeatures` and `BTM_SetPowerMode` to ensure SNIFF mode is
141       enabled.
142     - If the action chosen is `BTA_DM_PM_ACTIVE`, a call to `bta_dm_pm_active`
143       is made, which calls `BTM_SetPowerMode` to set the link into ACTIVE
144       mode.
145
146At this point, if one of the timers in `bta_dm_cb.pm_timer` times out, a call is
147made through the BTA workqueue thread to `bta_dm_pm_btm_cback`, which then
148triggers `bta_dm_pm_btm_status`, with the timeout field set to TRUE. HCI
149responses are also fired as messages through the BTA workqueue thread, which are
150handled again, through `bta_dm_pm_btm_status`.
151
152#### Events fired through BTM
153
154Essentially these messages eventually go through the same functions as events
155fired from the SYS side of things, except from the initial path they take:
156
157  1. An event is fired from a callback in BTM to `bta_dm_pm_btm_cback`.
158  2. `bta_dm_pm_btm_cback` packages up the given parameters into a
159     `tBTA_DM_PM_BTM_STATUS` struct and posts it to the BTA workqueue thread via
160     `bta_sys_sendmsg`, with the event header set to
161     `BTA_DM_PM_BTM_STATUS_EVT`.
162  3. This is eventually routed to the `bta_dm_pm_btm_status` function.
163     **Determine if this is running on the workqueue thread or not**
164     - The message `status` passed in is actually the current status of the
165       device.
166     - If the status is `BTM_PM_STS_ACTIVE` (still in the ACTIVE power mode),
167       checks the HCI status code:
168       - If that's non-zero and a PARK or SNIFF mode change was attempted,
169         `bta_dm_pm_btm_status` stops any timers started for the device in
170         `bta_dm_pm_set_mode`, clears some status bits in the peer device
171         structure, and then calls back into `bta_dm_pm_set_mode` with the peer
172         device address and timeout set to FALSE.
173       - If the status is zero, and if the peer device `tBTA_DM_PEER_DEVICE`
174         `prev_low` field is set, calls `bta_dm_pm_ssr` to re-send SSR params,
175         stops all timers for the device, and then re-calls `bta_dm_pm_set_mode`
176         with timeout set to FALSE to re-attempt with a second action (if the
177         previous PARK or SNIFF failed, otherwise it'll re-attempt the first
178         action).
179     - If the status is `BTM_PM_STS_PARK` or `BTM_PM_STS_HOLD`, saves the
180       previous low power mode in the peer device's `prev_low` field.
181     - If the status is `BTM_PM_STS_SSR`, simply clears or sets the device
182       `info` field's `BTA_DM_DI_USE_SSR` bit, depending on the value of
183       `tBTA_DM_MSG.value`, which determines if the device can handle SSR.
184     - If the status is `BTM_PM_STS_SNIFF` and the info field has the
185       `BTA_DM_DI_SET_SNIFF` bit set, then `BTA_DM_DI_INT_SNIFF` is set,
186       otherwise `BTA_DM_DI_ACP_SNIFF` is set.
187     - If `BTA_PM_STS_ERROR`, the `BTA_DM_DI_SET_SNIFF` bit is cleared in the
188       device info field.
189
190At this point, either the method simply returns, or has called back into
191`bta_dm_pm_set_mode`, in which case the usual flow takes over.
192
193#### Events fired from timers
194
195Timers are used exclusively for handling HCI command timeouts, and filter
196through to a call to `bta_dm_pm_set_mode`:
197
198  1. A timer expires, and calls `bta_dm_pm_timer_cback`.
199  2. `bta_dm_pm_timer_cback` clears the use flag on the timer that fired, and
200     sends off an event to the BTA workqueue thread.
201  3. The event eventually fires off a call to `bta_dm_pm_timer`, which just
202     calls `bta_dm_pm_set_mode` with timeout set to `TRUE`.
203