当有蓝牙耳机连接上时,系统由有线耳机切换到蓝牙耳机
一. 蓝牙耳机连上到audio的过程
对java不是很熟悉,大体上跟了一下代码
1. 当蓝牙耳机pair成功之后,会回调java
在蓝牙的packeges的app中,c回调java的
onConnectionStateChanged
./packages/apps/Bluetooth/jni/com_android_bluetooth_a2dp.cpp
-
static void classInitNative(JNIEnv* env, jclass clazz) {
-
method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
-
}
java的
onConnectionStateChanged又发送了一个EVENT_TYPE_CONNECTION_STATE_CHANGED的msg
./packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
-
private void onConnectionStateChanged(int state, byte[] address) {
-
StackEvent event = new StackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED);
-
event.valueInt = state;
-
event.device = getDevice(address);
-
sendMessage(STACK_EVENT, event);
-
}
在msg的处理Handler中:
-
private class IntentBroadcastHandler extends Handler { //b.msg处理
-
private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) {
-
Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
-
intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
-
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
-
mService.notifyProfileConnectionStateChanged(device, BluetoothProfile.A2DP, state, prevState);
-
}
-
-
@Override
-
public void handleMessage(Message msg) {
-
switch (msg.what) {
-
case MSG_CONNECTION_STATE_CHANGED:
-
onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2); //a.接收msg
-
mWakeLock.release();
-
break;
-
}
-
}
-
}
上面的回调了java的
onConnectionStateChanged,然后向AdapterService发送PROFILE_CONNECTION_STATE_CHANGED的消息
1.2 AdapterService接收到PROFILE_CONNECTION_STATE_CHANGED消息并处理
接收到这个
MESSAGE_PROFILE_CONNECTION_STATE_CHANGED
的msg,然后进调用processProfileStateChanged进行处理
./packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
-
public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
-
Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED);
-
m.obj = device;
-
m.arg1 = profileId;
-
m.arg2 = newState;
-
Bundle b = new Bundle(1);
-
b.putInt("prevState", prevState);
-
m.setData(b);
-
mHandler.sendMessage(m);
-
}
-
-
private final Handler mHandler = new Handler() {
-
@Override
-
public void handleMessage(Message msg) {
-
switch (msg.what) {
-
case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: {
-
processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR));
-
}
-
break;
-
}
-
}
-
};
处理函数就是调用Binder的
sendConnectionStateChange
-
private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
-
IBluetooth.Stub binder = mBinder;
-
binder.sendConnectionStateChange(device, profileId, newState,prevState);
-
}
AdapterProperties的处理就是发送一个广播
./packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
-
void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) {
-
synchronized (mObject) {
-
updateProfileConnectionState(profile, state, prevState);
-
if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
-
setConnectionState(state);
-
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
-
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, convertToAdapterState(state));
-
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, convertToAdapterState(prevState));
-
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
mService.sendBroadcastAsUser(intent, UserHandle.ALL, mService.BLUETOOTH_PERM);
-
}
-
}
-
}
AdapterService的处理就是发送一个ACTION_CONNECTION_STATE_CHANGED的广播
1.3 谁来接收这个广播呢?
AudioService在初始化时,创建了intentFilter,就可以接收ACTION_CONNECTION_STATE_CHANGED
./frameworks/base/media/java/android/media/AudioService.java
-
public AudioService(Context context) {
-
intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); //初始化时,添加Filter
-
}
-
private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
-
if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
-
//handleDeviceConnection(connected, device, address) //handle的处理就是调用AudioSystem的函数
-
AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE, params);
-
}
-
}
AudioSystem调用jni,由java进入c
./frameworks/base/media/java/android/media/AudioSystem.java
-
public static native int setDeviceConnectionState(int device, int state, String device_address);
2. JNI
./frameworks/base/core/jni/android_media_AudioSystem.cpp
-
android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
-
{
-
const char *c_address = env->GetStringUTFChars(device_address, NULL);
-
int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
-
static_cast <audio_policy_dev_state_t>(state),
-
c_address));
-
env->ReleaseStringUTFChars(device_address, c_address);
-
return status;
-
}
2.1 进入AudioSystem.cpp
./frameworks/av/media/libmedia/AudioSystem.cpp
-
status_t AudioSystem::setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address)
-
{
-
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
-
if (device_address != NULL) {
-
address = device_address;
-
}
-
return aps->setDeviceConnectionState(device, state, address);
-
}
./frameworks/av/media/libmedia/AudioPolicyService.cpp
-
status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,)
-
{
-
return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device, state, device_address);
-
}
3. audio_policy.default.so
-
status_t AudioPolicyManagerBase::setDeviceConnectionState(audio_devices_t device,
-
AudioSystem::device_connection_state state,
-
const char *device_address)
-
{
-
//先判断是输入输出:
-
硬件上己知是蓝牙设备,
-
蓝牙设备的标识 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET=0x20
-
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP=0x80
-
然后再根据这个标识去查表即可判断是输出还是输出
-
}
现在己经明白了,为什么回调时会到了audio_policy_default.so,
原因是回调时发了一个广播,这个广播时由AudioService接收的,AudioService又经过Jni等,调到了c层
阅读(1730) | 评论(0) | 转发(0) |