BluetoothAvrcpController,没有提供协议连接和断开的接口,那AVRCP协议是如何连接的呢?因为AVRCP和A2DP协议通常都是一起使用的,A2DP连接成功后,蓝牙协议栈(BT Stack)会主动发起AVRCP的连接,具体可以查看android部分源码。
AVRCP的连接也涉及到了两条通道的建立:控制通道 + 浏览通道(双方都支持浏览功能),那次协议的连接流程主要是建立两条L2CAP链路的过程,但第一步还是发起SDP服务,这是蓝牙连接中必不可少的一环。连接的时序简图如下:
蓝牙协议栈(BT Stack)相关我们不再这里分析,我们从JNI开始分析:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_avrcp_controller.cpp
static void btavrcp_connection_state_callback(bool rc_connect, bool br_connect,
const RawAddress& bd_addr) {
ALOGI("%s: conn state: rc: %d br: %d", __func__, rc_connect, br_connect);
std::shared_lock<std::shared_timed_mutex> lock(sCallbacks_mutex);
CallbackEnv sCallbackEnv(__func__);
if (!sCallbackEnv.valid()) return;
if (!sCallbacksObj) {
ALOGE("%s: sCallbacksObj is null", __func__);
return;
}
ScopedLocalRef<jbyteArray> addr(
sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
if (!addr.get()) {
ALOGE("%s: Failed to allocate a new byte array", __func__);
return;
}
sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
(jbyte*)bd_addr.address); //设置字节数组区域
sCallbackEnv->CallVoidMethod(sCallbacksObj, method_onConnectionStateChanged,
(jboolean)rc_connect, (jboolean)br_connect,
addr.get()); //调用 void 方法
}
通过sCallbackEnv->CallVoidMethod调用method_onConnectionStateChanged方法,通过classInitNative对应的JAVA方法:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_avrcp_controller.cpp
static void classInitNative(JNIEnv* env, jclass clazz) {
method_onConnectionStateChanged =
env->GetMethodID(clazz, "onConnectionStateChanged", "(ZZ[B)V");
}
AvrcpControllerService onConnectionStateChanged
调用AvrcpControllerService的onConnectionStateChanged方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
public class AvrcpControllerService extends ProfileService {
// Called by JNI when a device has connected or disconnected.
private synchronized void onConnectionStateChanged(boolean remoteControlConnected,
boolean browsingConnected, byte[] address) {
BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
if (DBG) {
Log.d(TAG, "onConnectionStateChanged " + remoteControlConnected + " "
+ browsingConnected + device);
}
if (device == null) {
Log.e(TAG, "onConnectionStateChanged Device is null");
return;
}
StackEvent event =
StackEvent.connectionStateChanged(remoteControlConnected, browsingConnected);
AvrcpControllerStateMachine stateMachine = getOrCreateStateMachine(device);
if (remoteControlConnected || browsingConnected) {
stateMachine.connect(event);
// The first device to connect gets to be the active device
if (getActiveDevice() == null) {
setActiveDevice(device);
}
} else {
stateMachine.disconnect();
if (device.equals(getActiveDevice())) {
setActiveDevice(null);
}
}
}
}
以上方法主要的处理如下:
1、调用AvrcpControllerStateMachine的connect方法,通过状态机处理Avrcp的connect。
2、调用AvrcpControllerService setActiveDevice方法,设置活动设备。
下面分别进行分析:
AvrcpControllerStateMachine connect
调用StackEvent的connectionStateChanged方法,创建EVENT_TYPE_CONNECTION_STATE_CHANGED的StackEvent:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/StackEvent.java
final class StackEvent {
static StackEvent connectionStateChanged(boolean remoteControlConnected,
boolean browsingConnected) {
StackEvent event = new StackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED);
event.mRemoteControlConnected = remoteControlConnected;
event.mBrowsingConnected = browsingConnected;
return event;
}
}
调用AvrcpControllerStateMachine的connect方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpNativeInterface.java
class AvrcpControllerStateMachine extends StateMachine {
public boolean connect(StackEvent event) {
if (event.mBrowsingConnected) {
onBrowsingConnected();
}
mRemoteControlConnected = event.mRemoteControlConnected;
sendMessage(CONNECT);
return true;
}
}
上面方法的主要处理如下:
1、调用AvrcpControllerStateMachine的onBrowsingConnected方法,用于处理Avrcp浏览连接
2、发送CONNECT消息
下面分别进行分析:
AvrcpControllerStateMachine onBrowsingConnected
调用AvrcpControllerStateMachine的onBrowsingConnected方法,用于处理Avrcp浏览连接:
/packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpNativeInterface.java
class AvrcpControllerStateMachine extends StateMachine {
synchronized void onBrowsingConnected() {
mBrowsingConnected = true;
requestContents(mBrowseTree.mRootNode);
}
}
调用AvrcpControllerStateMachine的requestContents方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpNativeInterface.java
class AvrcpControllerStateMachine extends StateMachine {
void requestContents(BrowseTree.BrowseNode node) {
sendMessage(MESSAGE_GET_FOLDER_ITEMS, node);
logD("Fetching " + node);
}
}
发送MESSAGE_GET_FOLDER_ITEMS消息,消息在AvrcpControllerStateMachine的内部类Connected的processMessage方法中处理:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpNativeInterface.java
class AvrcpControllerStateMachine extends StateMachine {
class Connected extends State {
public boolean processMessage(Message msg) {
logD(STATE_TAG + " processMessage " + msg.what);
switch (msg.what) {
case MESSAGE_GET_FOLDER_ITEMS:
transitionTo(mGetFolderList); //迁移到GetFolderList状态
return true;
}
}
}
}
迁移到GetFolderList状态,会调用GetFolderList状态的enter方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpNativeInterface.java
class AvrcpControllerStateMachine extends StateMachine {
class GetFolderList extends State {
@Override
public void enter() {
logD(STATE_TAG + " Entering GetFolderList");
// Setup the timeouts.
sendMessageDelayed(MESSAGE_INTERNAL_CMD_TIMEOUT, CMD_TIMEOUT_MILLIS);
super.enter();
mAbort = false;
Message msg = getCurrentMessage();
if (msg.what == MESSAGE_GET_FOLDER_ITEMS) {
{
logD(STATE_TAG + " new Get Request");
mBrowseNode = (BrowseTree.BrowseNode) msg.obj;
}
}
if (mBrowseNode == null) {
transitionTo(mConnected); //如果浏览节点为空,将状态迁移到Connected状态
} else {
navigateToFolderOrRetrieve(mBrowseNode);
}
}
}
}
调用navigateToFolderOrRetrieve方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpNativeInterface.java
class AvrcpControllerStateMachine extends StateMachine {
protected final AvrcpControllerService mService;
class GetFolderList extends State {
BrowseTree.BrowseNode mBrowseNode;
BrowseTree.BrowseNode mNextStep;
private void navigateToFolderOrRetrieve(BrowseTree.BrowseNode target) {
mNextStep = mBrowseTree.getNextStepToFolder(target);
logD("NAVIGATING From "
+ mBrowseTree.getCurrentBrowsedFolder().toString());
logD("NAVIGATING Toward " + target.toString());
if (mNextStep == null) {
return;
} else if (target.equals(mBrowseTree.mNowPlayingNode)
|| target.equals(mBrowseTree.mRootNode)
|| mNextStep.equals(mBrowseTree.getCurrentBrowsedFolder())) {
fetchContents(mNextStep); //从远程设备中获取指定的媒体内容
} else if (mNextStep.isPlayer()) {
logD("NAVIGATING Player " + mNextStep.toString());
if (mNextStep.isBrowsable()) {
mService.setBrowsedPlayerNative(
mDeviceAddress, (int) mNextStep.getBluetoothID());
} else {
logD("Player doesn't support browsing");
mNextStep.setCached(true);
transitionTo(mConnected);
}
} else if (mNextStep.equals(mBrowseTree.mNavigateUpNode)) {
logD("NAVIGATING UP " + mNextStep.toString());
mNextStep = mBrowseTree.getCurrentBrowsedFolder().getParent();
mBrowseTree.getCurrentBrowsedFolder().setCached(false);
removeUnusedArtworkFromBrowseTree();
mService.changeFolderPathNative(
mDeviceAddress,
AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_UP,
0);
} else {
logD("NAVIGATING DOWN " + mNextStep.toString());
mService.changeFolderPathNative(
mDeviceAddress,
AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_DOWN,
mNextStep.getBluetoothID());
}
}
}
}
上面方法的主要处理如下:
1、调用AvrcpControllerStateMachine的fetchContents,从远程设备中获取指定的媒体内容
2、调用AvrcpControllerService的setBrowsedPlayerNative方法
3、调用AvrcpControllerService的changeFolderPathNative方法
下面分别进行分析:
AvrcpControllerStateMachine fetchContents
调用AvrcpControllerStateMachine的fetchContents,从远程设备中获取指定的媒体内容:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpNativeInterface.java
class AvrcpControllerStateMachine extends StateMachine {
protected final AvrcpControllerService mService;
class GetFolderList extends State {
private void fetchContents(BrowseTree.BrowseNode target) {
int start = target.getChildrenCount();
int end = Math.min(target.getExpectedChildren(), target.getChildrenCount()
+ ITEM_PAGE_SIZE) - 1;
logD("fetchContents(title=" + target.getID() + ", scope=" + target.getScope()
+ ", start=" + start + ", end=" + end + ", expected="
+ target.getExpectedChildren() + ")");
switch (target.getScope()) {
case AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST:
mService.getPlayerListNative(mDeviceAddress,
start, end);
break;
case AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING:
mService.getNowPlayingListNative(
mDeviceAddress, start, end);
break;
case AvrcpControllerService.BROWSE_SCOPE_VFS:
mService.getFolderListNative(mDeviceAddress,
start, end);
break;
default:
Log.e(TAG, STATE_TAG + " Scope " + target.getScope()
+ " cannot be handled here.");
}
}
}
}
上面方法主要的处理如下:
1、调用AvrcpControllerService的getPlayerListNative方法
2、调用AvrcpControllerService的getNowPlayingListNative方法
3、调用AvrcpControllerService的getFolderListNative方法
AvrcpControllerService getPlayerListNative
调用AvrcpControllerService的getPlayerListNative方法,getPlayerListNative是一个Native方法,实现如下:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_avrcp_controller.cpp
static const btrc_ctrl_interface_t* sBluetoothAvrcpInterface = NULL;
static void getPlayerListNative(JNIEnv* env, jobject object, jbyteArray address,
jint start, jint end) {
if (!sBluetoothAvrcpInterface) return;
jbyte* addr = env->GetByteArrayElements(address, NULL);
if (!addr) {
jniThrowIOException(env, EINVAL);
return;
}
ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
RawAddress rawAddress;
rawAddress.FromOctets((uint8_t*)addr);
bt_status_t status =
sBluetoothAvrcpInterface->get_player_list_cmd(rawAddress, start, end);
if (status != BT_STATUS_SUCCESS) {
ALOGE("Failed sending getPlayerListNative command, status: %d", status);
}
env->ReleaseByteArrayElements(address, addr, 0);
}
调用btrc_ctrl_interface_t的get_player_list_cmd函数,btrc_ctrl_interface_t是一个结构体,在bt_rc.h定义,在btif_rc.cc中实现:
//packages/modules/Bluetooth/system/btif/src/btif_rc.cc
static bt_status_t get_player_list_cmd(const RawAddress& bd_addr,
uint32_t start_item, uint32_t end_item) {
BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item,
end_item);
}
在之后就是蓝牙协议栈相关内容,在这里就不再分析了。
AvrcpControllerService getNowPlayingListNative
调用AvrcpControllerService的getNowPlayingListNative方法,getNowPlayingListNative是一个Native方法,实现如下:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_avrcp_controller.cpp
static const btrc_ctrl_interface_t* sBluetoothAvrcpInterface = NULL;
static void getNowPlayingListNative(JNIEnv* env, jobject object,
jbyteArray address, jint start, jint end) {
if (!sBluetoothAvrcpInterface) return;
jbyte* addr = env->GetByteArrayElements(address, NULL);
if (!addr) {
jniThrowIOException(env, EINVAL);
return;
}
ALOGV("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
RawAddress rawAddress;
rawAddress.FromOctets((uint8_t*)addr);
bt_status_t status = sBluetoothAvrcpInterface->get_now_playing_list_cmd(
rawAddress, start, end);
if (status != BT_STATUS_SUCCESS) {
ALOGE("Failed sending getNowPlayingListNative command, status: %d", status);
}
env->ReleaseByteArrayElements(address, addr, 0);
}
调用btrc_ctrl_interface_t的get_now_playing_list_cmd函数,btrc_ctrl_interface_t是一个结构体,在bt_rc.h定义,在btif_rc.cc中实现:
//packages/modules/Bluetooth/system/btif/src/btif_rc.cc
static bt_status_t get_now_playing_list_cmd(const RawAddress& bd_addr,
uint32_t start_item,
uint32_t end_item) {
BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
return get_folder_items_cmd(bd_addr, AVRC_SCOPE_NOW_PLAYING, start_item,
end_item);
}
在之后就是蓝牙协议栈相关内容,在这里就不再分析了。
AvrcpControllerService getFolderListNative
调用AvrcpControllerService的getFolderListNative方法,getFolderListNative是一个Native方法,实现如下:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_avrcp_controller.cpp
static const btrc_ctrl_interface_t* sBluetoothAvrcpInterface = NULL;
static void getFolderListNative(JNIEnv* env, jobject object, jbyteArray address,
jint start, jint end) {
if (!sBluetoothAvrcpInterface) return;
jbyte* addr = env->GetByteArrayElements(address, NULL);
if (!addr) {
jniThrowIOException(env, EINVAL);
return;
}
ALOGV("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
RawAddress rawAddress;
rawAddress.FromOctets((uint8_t*)addr);
bt_status_t status =
sBluetoothAvrcpInterface->get_folder_list_cmd(rawAddress, start, end);
if (status != BT_STATUS_SUCCESS) {
ALOGE("Failed sending getFolderListNative command, status: %d", status);
}
env->ReleaseByteArrayElements(address, addr, 0);
}
调用btrc_ctrl_interface_t的get_player_list_cmd函数,btrc_ctrl_interface_t是一个结构体,在bt_rc.h定义,在btif_rc.cc中实现:
//packages/modules/Bluetooth/system/btif/src/btif_rc.cc
static bt_status_t get_folder_list_cmd(const RawAddress& bd_addr,
uint32_t start_item, uint32_t end_item) {
BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
return get_folder_items_cmd(bd_addr, AVRC_SCOPE_FILE_SYSTEM, start_item,
end_item);
}
在之后就是蓝牙协议栈相关内容,在这里就不再分析了。
AvrcpControllerService setBrowsedPlayerNative
调用AvrcpControllerService的setBrowsedPlayerNative方法,setBrowsedPlayerNative是一个Native方法,实现如下:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_avrcp_controller.cpp
static const btrc_ctrl_interface_t* sBluetoothAvrcpInterface = NULL;
static void setBrowsedPlayerNative(JNIEnv* env, jobject object,
jbyteArray address, jint id) {
if (!sBluetoothAvrcpInterface) return;
jbyte* addr = env->GetByteArrayElements(address, NULL);
if (!addr) {
jniThrowIOException(env, EINVAL);
return;
}
RawAddress rawAddress;
rawAddress.FromOctets((uint8_t*)addr);
ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
bt_status_t status = sBluetoothAvrcpInterface->set_browsed_player_cmd(
rawAddress, (uint16_t)id);
if (status != BT_STATUS_SUCCESS) {
ALOGE("Failed sending setBrowsedPlayerNative command, status: %d", status);
}
env->ReleaseByteArrayElements(address, addr, 0);
}
调用btrc_ctrl_interface_t的get_player_list_cmd函数,btrc_ctrl_interface_t是一个结构体,在bt_rc.h定义,在btif_rc.cc中实现:
//packages/modules/Bluetooth/system/btif/src/btif_rc.cc
static bt_status_t get_player_list_cmd(const RawAddress& bd_addr,
uint32_t start_item, uint32_t end_item) {
BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, end_item);
return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item,
end_item);
}
在之后就是蓝牙协议栈相关内容,在这里就不再分析了。
AvrcpControllerService changeFolderPathNative
调用AvrcpControllerService的changeFolderPathNative方法,changeFolderPathNative是一个Native方法,实现如下:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_avrcp_controller.cpp
static const btrc_ctrl_interface_t* sBluetoothAvrcpInterface = NULL;
static void changeFolderPathNative(JNIEnv* env, jobject object,
jbyteArray address, jbyte direction,
jlong uid) {
if (!sBluetoothAvrcpInterface) return;
jbyte* addr = env->GetByteArrayElements(address, NULL);
if (!addr) {
jniThrowIOException(env, EINVAL);
return;
}
// jbyte* uid = env->GetByteArrayElements(uidarr, NULL);
// if (!uid) {
// jniThrowIOException(env, EINVAL);
// return;
//}
ALOGI("%s: sBluetoothAvrcpInterface: %p", __func__, sBluetoothAvrcpInterface);
RawAddress rawAddress;
rawAddress.FromOctets((uint8_t*)addr);
bt_status_t status = sBluetoothAvrcpInterface->change_folder_path_cmd(
rawAddress, (uint8_t)direction, (uint8_t*)&uid);
if (status != BT_STATUS_SUCCESS) {
ALOGE("Failed sending changeFolderPathNative command, status: %d", status);
}
// env->ReleaseByteArrayElements(address, addr, 0);
}
调用btrc_ctrl_interface_t的get_player_list_cmd函数,btrc_ctrl_interface_t是一个结构体,在bt_rc.h定义,在btif_rc.cc中实现:
//packages/modules/Bluetooth/system/btif/src/btif_rc.cc
static bt_status_t change_folder_path_cmd(const RawAddress& bd_addr,
uint8_t direction, uint8_t* uid) {
BTIF_TRACE_DEBUG("%s: direction %d", __func__, direction);
btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
CHECK_RC_CONNECTED(p_dev);
CHECK_BR_CONNECTED(p_dev);
tAVRC_COMMAND avrc_cmd = {0};
avrc_cmd.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
avrc_cmd.chg_path.status = AVRC_STS_NO_ERROR;
// TODO(sanketa): Improve for database aware clients.
avrc_cmd.chg_path.uid_counter = 0;
avrc_cmd.chg_path.direction = direction;
memset(avrc_cmd.chg_path.folder_uid, 0, AVRC_UID_SIZE * sizeof(uint8_t));
memcpy(avrc_cmd.chg_path.folder_uid, uid, AVRC_UID_SIZE * sizeof(uint8_t));
return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
}
在之后就是蓝牙协议栈相关内容,在这里就不再分析了。
AvrcpControllerService setActiveDevice
调用AvrcpControllerService setActiveDevice方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
public class AvrcpControllerService extends ProfileService {
private boolean setActiveDevice(BluetoothDevice device) {
A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService();
if (a2dpSinkService == null) {
return false;
}
BluetoothDevice currentActiveDevice = getActiveDevice();
if ((device == null && currentActiveDevice == null) //由于是disconnect,传入的device 为null,因此直接返回true
|| (device != null && device.equals(currentActiveDevice))) {
return true;
}
// Try and update the active device
synchronized (mActiveDeviceLock) {
if (a2dpSinkService.setActiveDevice(device)) {
mActiveDevice = device;
// Pause the old active device
if (currentActiveDevice != null) {
AvrcpControllerStateMachine oldStateMachine =
getStateMachine(currentActiveDevice);
if (oldStateMachine != null) {
oldStateMachine.setDeviceState(DEVICE_STATE_INACTIVE);
}
}
AvrcpControllerStateMachine stateMachine = getStateMachine(device);
if (stateMachine != null) {
stateMachine.setDeviceState(DEVICE_STATE_ACTIVE);
} else {
BluetoothMediaBrowserService.reset();
}
return true;
}
}
return false;
}
}
到这里BluetoothAvrcp connect流程就介绍完了。