蓝牙avrcp协议源码分析

1,概述

1.1 avrcp协议

全称: Audio / Video Remote Control Profile音/视频远程控制协议

使用场景:不仅控制音频/视频,主要相当于一个远程遥控器,浏览手机上的文件,调整电视机上的菜单等等。

市场产品:蓝牙耳机,蓝牙遥控器,蓝牙自拍干等等

技术知识:

    控制器: 远程控制设备,比如蓝牙自拍干

    目标设备:比如手机,电视机

 

1.2 代码路径

客户端: frameworks\base\core\java\android\bluetooth

  BluetoothAvrcp.java            定义的A/V 控制信号

  BluetoothAvrcpController.java    协议的客户端

  BluetoothAvrcpInfo.java         目标设备的元数据

服务端: packages\apps\Bluetooth\src\com\android\bluetooth\ avrcp

AvrcpControllerService.java       协议的服务端

BluetoothAvrcpDataProvider.java   元数据的数据库

Avrcp.java  还不知道这个类具体做什么的

2,接口

蓝牙遥控器的原理其实很简单,发送一个A/V控制信号就可以, BluetoothAvrcp文件提供了丰富的控制信号,简直就是一个遥控器。

public final class BluetoothAvrcp {
    /*
     * State flags for Passthrough commands
    */
    public static final int PASSTHROUGH_STATE_PRESS    = 0;
    public static final int PASSTHROUGH_STATE_RELEASE  = 1;

    /*
     * Operation IDs for Passthrough commands
    */
    public static final int PASSTHROUGH_ID_SELECT      = 0x00;    /* select */
    public static final int PASSTHROUGH_ID_UP          = 0x01;    /* up */
    public static final int PASSTHROUGH_ID_DOWN        = 0x02;    /* down */
    public static final int PASSTHROUGH_ID_LEFT        = 0x03;    /* left */
    public static final int PASSTHROUGH_ID_RIGHT       = 0x04;    /* right */
    public static final int PASSTHROUGH_ID_RIGHT_UP    = 0x05;    /* right-up */
    public static final int PASSTHROUGH_ID_RIGHT_DOWN  = 0x06;    /* right-down */
    public static final int PASSTHROUGH_ID_LEFT_UP     = 0x07;    /* left-up */
    public static final int PASSTHROUGH_ID_LEFT_DOWN   = 0x08;    /* left-down */
    public static final int PASSTHROUGH_ID_ROOT_MENU   = 0x09;    /* root menu */
    public static final int PASSTHROUGH_ID_SETUP_MENU  = 0x0A;    /* setup menu */
    public static final int PASSTHROUGH_ID_CONT_MENU   = 0x0B;    /* contents menu */
    public static final int PASSTHROUGH_ID_FAV_MENU    = 0x0C;    /* favorite menu */
    public static final int PASSTHROUGH_ID_EXIT        = 0x0D;    /* exit */
    public static final int PASSTHROUGH_ID_0           = 0x20;    /* 0 */
    public static final int PASSTHROUGH_ID_1           = 0x21;    /* 1 */
    public static final int PASSTHROUGH_ID_2           = 0x22;    /* 2 */
    public static final int PASSTHROUGH_ID_3           = 0x23;    /* 3 */
    public static final int PASSTHROUGH_ID_4           = 0x24;    /* 4 */
    public static final int PASSTHROUGH_ID_5           = 0x25;    /* 5 */
    public static final int PASSTHROUGH_ID_6           = 0x26;    /* 6 */
    public static final int PASSTHROUGH_ID_7           = 0x27;    /* 7 */
    public static final int PASSTHROUGH_ID_8           = 0x28;    /* 8 */
    public static final int PASSTHROUGH_ID_9           = 0x29;    /* 9 */
    public static final int PASSTHROUGH_ID_DOT         = 0x2A;    /* dot */
    public static final int PASSTHROUGH_ID_ENTER       = 0x2B;    /* enter */
    public static final int PASSTHROUGH_ID_CLEAR       = 0x2C;    /* clear */
    public static final int PASSTHROUGH_ID_CHAN_UP     = 0x30;    /* channel up */
    public static final int PASSTHROUGH_ID_CHAN_DOWN   = 0x31;    /* channel down */
    public static final int PASSTHROUGH_ID_PREV_CHAN   = 0x32;    /* previous channel */
    public static final int PASSTHROUGH_ID_SOUND_SEL   = 0x33;    /* sound select */
    public static final int PASSTHROUGH_ID_INPUT_SEL   = 0x34;    /* input select */
    public static final int PASSTHROUGH_ID_DISP_INFO   = 0x35;    /* display information */
    public static final int PASSTHROUGH_ID_HELP        = 0x36;    /* help */
    public static final int PASSTHROUGH_ID_PAGE_UP     = 0x37;    /* page up */
    public static final int PASSTHROUGH_ID_PAGE_DOWN   = 0x38;    /* page down */
    public static final int PASSTHROUGH_ID_POWER       = 0x40;    /* power */
    public static final int PASSTHROUGH_ID_VOL_UP      = 0x41;    /* volume up */
    public static final int PASSTHROUGH_ID_VOL_DOWN    = 0x42;    /* volume down */
    public static final int PASSTHROUGH_ID_MUTE        = 0x43;    /* mute */
    public static final int PASSTHROUGH_ID_PLAY        = 0x44;    /* play */
    public static final int PASSTHROUGH_ID_STOP        = 0x45;    /* stop */
    public static final int PASSTHROUGH_ID_PAUSE       = 0x46;    /* pause */
    public static final int PASSTHROUGH_ID_RECORD      = 0x47;    /* record */
    public static final int PASSTHROUGH_ID_REWIND      = 0x48;    /* rewind */
    public static final int PASSTHROUGH_ID_FAST_FOR    = 0x49;    /* fast forward */
    public static final int PASSTHROUGH_ID_EJECT       = 0x4A;    /* eject */
    public static final int PASSTHROUGH_ID_FORWARD     = 0x4B;    /* forward */
    public static final int PASSTHROUGH_ID_BACKWARD    = 0x4C;    /* backward */
    public static final int PASSTHROUGH_ID_ANGLE       = 0x50;    /* angle */
    public static final int PASSTHROUGH_ID_SUBPICT     = 0x51;    /* subpicture */
    public static final int PASSTHROUGH_ID_F1          = 0x71;    /* F1 */
    public static final int PASSTHROUGH_ID_F2          = 0x72;    /* F2 */
    public static final int PASSTHROUGH_ID_F3          = 0x73;    /* F3 */
    public static final int PASSTHROUGH_ID_F4          = 0x74;    /* F4 */
    public static final int PASSTHROUGH_ID_F5          = 0x75;    /* F5 */
    public static final int PASSTHROUGH_ID_VENDOR      = 0x7E;    /* vendor unique */
    public static final int PASSTHROUGH_KEYPRESSED_RELEASE = 0x80;
}

发送控制信号的BluetoothAvrcpController接口sendPassThroughCmd如下:

public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) {
        if (DBG) Log.d(TAG, "sendPassThroughCmd dev = " + device + " key " + 
               keyCode + " State = " + keyState);
        if (mService != null && isEnabled()) {
            try {
                mService.sendPassThroughCmd(device, keyCode, keyState);
                return;
            } catch (RemoteException e) {
                Log.e(TAG, "Error talking to BT service in sendPassThroughCmd()", e);
                return;
            }
        }
        if (mService == null) Log.w(TAG, "Proxy not attached to service");
    }

其中, BluetoothDevice是目标设备的蓝牙设备, keyCode是控制信号的键值, keyState 是键值的状态,0表示按下,1表示释放。

直接调用服务端(AvrcpControllerService)的sendPassThroughCmd方法,

比如,自己做开发时,发送暂停控制信号,

 public static final int AVRC_ID_PAUSE = 0x46;
    public static final int KEY_STATE_PRESSED = 0;
    public static final int KEY_STATE_RELEASED = 1;

public boolean SendPassThruPause(BluetoothDevice mDevice) {
if ((mAvrcpController != null) && (mDevice != null) &&
        (BluetoothProfile.STATE_DISCONNECTED != 
                 (mAvrcpController.getConnectionState(mDevice)))){
	   mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_PAUSE, KEY_STATE_PRESSED);
    mAvrcpController.sendPassThroughCmd(mDevice, AVRC_ID_PAUSE, KEY_STATE_RELEASED);
       return true;
    } else {
    	return false;
    }

3,小结

avrcp协议虽然使用简单,但是能做很多事情,还有疑惑的地方:

1,BluetoothAvrcpInfo.java和Avrcp.java 不知道具体做什么的

2, BluetoothAvrcpController的getMetaData接口本意是获取元数据,但是又没有返回值

3,服务端AvrcpControllerService的方法比客户端的方法要多很多,也不知道有什么作用。



你可能感兴趣的:(---【蓝牙框架分析】)