在Android蓝牙协议栈fluoride(五) - 设备管理(bt application)中描述了设备管理中的API、状态机以及事件处理,接下来将描述设备管理中的功耗管理和上报到上层的事件。
功耗管理
连接策略
蓝牙设备有很大比例都是带电池的产品,那么功耗的高低直接决定了使用时间的长短,蓝牙在工作时有时候需要连续传输数据或者实时的传输数据(如播放音乐/通话等),有时仅仅建立了连接并没有业务处理(如音乐暂停但连接并未断开),那么就希望有业务时能实时的传输数据,没有业务时保持连接的同时有较低的功耗,因此就产生以下模式(策略):
- active模式
有业务时实时(宏观上)传输数据。
- sniff模式
没有业务时定期发送心跳保持连接,待有业务时切换到active模式。
- hold模式
该模式下,不支持ACL通道上的数据传输(SCO通道可以传输数据),因此设备可以利用这个时间段完成其他业务,如scan、page、inquiry等。
所以在在蓝牙设备使用过程中,在有业务时将链接策略设置为active模式,在没有业务的时候设置为sniff模式或者hold模式节省功耗。
在代码中,系统管理器提供了以下几个接口设置链接策略:
// 设置/清除策略
void bta_sys_set_policy(uint8_t id, uint8_t policy, const RawAddress& peer_addr);
void bta_sys_clear_policy(uint8_t id, uint8_t policy, const RawAddress& peer_addr);
// 设置/清除默认设置
void bta_sys_set_default_policy(uint8_t id, uint8_t policy);
void bta_sys_clear_default_policy(uint8_t id, uint8_t policy);
以上接口都是调用设备管理中的bta_dm_policy_cback
回调,该回调通过 bta_sys_policy_register
注册。这个回调中分别调用BTM_SetLinkPolicy
和BTM_SetDefaultLinkPolicy
实现。
参数设置
各个的profile在不同状态下设置不同参数,在设备管理器中按照生成以下几个表,每个表之间建立映射关系,设置参数时查表设置。
typedef struct {
uint8_t id; //模块ID
uint8_t app_id; //App ID
uint8_t spec_idx; // tBTA_DM_PM_SPEC表中的index
} tBTA_DM_PM_CFG;
typedef struct {
tBTA_DM_PM_ACTION power_mode; // 连接策略
uint16_t timeout; // 当前策略的超时时间
} tBTA_DM_PM_ACTN;
typedef struct {
uint8_t allow_mask; //运行的策略的mask
uint8_t ssr;
tBTA_DM_PM_ACTN actn_tbl[BTA_DM_PM_NUM_EVTS][2]; // 各个profile不同状态下的策略和超时时间,策略的参数在tBTM_PM_PWR_MD中
} tBTA_DM_PM_SPEC;
typedef struct {
uint16_t max;
uint16_t min;
uint16_t attempt;
uint16_t timeout;
tBTM_PM_MODE mode;
} tBTM_PM_PWR_MD;
注: Core 5.3删除了park模式,本系列文章不再介绍,有文章中有出现请忽略
代码中这三个表格实现如下:
tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1] = {
{
BTA_ID_SYS, BTA_DM_NUM_PM_ENTRY, 0}, /* reserved: specifies length of this table. */
{
BTA_ID_AG, BTA_ALL_APP_ID, 0}, /* ag uses first spec table for app id 0 */
{
BTA_ID_CT, 1, 1}, /* ct (BTA_ID_CT,APP ID=1) spec table */
{
BTA_ID_CG, BTA_ALL_APP_ID, 1}, /* cg resue ct spec table */
...
};
tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
/* AG : 0 */
{
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
(BTA_DM_PM_SSR2), /* the SSR entry */
{
{
{
BTA_DM_PM_SNIFF_A2DP_IDX, 7000},
{
BTA_DM_PM_NO_ACTION