前面讲到AudioFlinger打开设备,但是后面贴了图片就没继续了,现在继续看看:
audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, audio_devices_t *pDevices, uint32_t *pSamplingRate, audio_format_t *pFormat, audio_channel_mask_t *pChannelMask, uint32_t *pLatencyMs, audio_output_flags_t flags)
就这个地方了!
准备打开如下:
outHwDev = findSuitableHwDev_l(module, *pDevices); if (outHwDev == NULL) return 0; audio_hw_device_t *hwDevHal = outHwDev->hwDevice();
先查找适合的设备,然后在打开,查找适合的设备如下:
AudioFlinger::AudioHwDevice* AudioFlinger::findSuitableHwDev_l( audio_module_handle_t module, audio_devices_t devices) { // if module is 0, the request comes from an old policy manager and we should load // well known modules if (module == 0) { ALOGW("findSuitableHwDev_l() loading well know audio hw modules"); for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) { loadHwModule_l(audio_interfaces[i]); } // then try to find a module supporting the requested device. for (size_t i = 0; i < mAudioHwDevs.size(); i++) { AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i); audio_hw_device_t *dev = audioHwDevice->hwDevice(); if ((dev->get_supported_devices != NULL) && (dev->get_supported_devices(dev) & devices) == devices) return audioHwDevice; } } else { // check a match for the requested module handle AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(module); if (audioHwDevice != NULL) { return audioHwDevice; } } return NULL; }
这个地方有两个遍历:
<1> : 遍历了所有的interfaces,这个接口非常的重要,就相当于通向不同设备的道路的大门,一般较多的AudioHardwareInterface,AudioHardwareA2dpInterface等等,使用不同的接口,就以为的操作不同的接口了!
<2> : 遍历了所有的设备,然后选择支持的设备返回,上面有name参考,打印出来即primary,a2dp,usb等等
然后通过上面返回的设备打开设备流:
status = hwDevHal->open_output_stream(hwDevHal, id, *pDevices, (audio_output_flags_t)flags, &config, &outStream);
然后创建播放线程:
if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || (config.format != AUDIO_FORMAT_PCM_16_BIT) || (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output, id, *pDevices); ALOGV("openOutput() created direct output: ID %d thread %p", id, thread); } else { thread = new MixerThread(this, output, id, *pDevices); ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread); } mPlaybackThreads.add(id, thread);
将穿件的播放线程添加到mPlaybackThreads中,AudioFlinger,创建好的线程会把该线程和它的Id保存在AudioFlinger的成员变量mPlaybackThreads 中,mPlaybackThreads是一个Vector,AudioFlinger创建的线程都会保存在里面,最后,openOutput返回该线程的 Id,该Id也就是所谓的audio_io_handle_t,AudioFlinger的调用者这能看到这个audio_io_handle_t,当需 要访问时传入该audio_io_handle_t,AudioFlinger会通过mPlaybackThreads,得到该线程的指针.所以可以每个播放都是拥有自己的播放线程的.
只有在音频数据处理上可能会MIXER.
下面来看看设备是如何切换的,比如蓝牙设备接入,并且要"替代"Speaker.
你可以从AudioManager.java调用setBluetoothA2dpOn开始看起,但是这里直接开始在AudioService.java看起:
/** @see AudioManager#setBluetoothA2dpOn() */ public void setBluetoothA2dpOn(boolean on) { synchronized (mBluetoothA2dpEnabledLock) { mBluetoothA2dpEnabled = on; sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, AudioSystem.FOR_MEDIA, mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, null, 0); } }
一看这个sendMsg是需要mAudioHandler来处理的,那么mAudioHandler是如何处理的呢?
/** Handles internal volume messages in separate volume thread. */ private class AudioHandler extends Handler { private void setDeviceVolume(VolumeStreamState streamState, int device) { // Apply volume streamState.applyDeviceVolume(device); // Apply change to all streams using this one as alias int numStreamTypes = AudioSystem.getNumStreamTypes(); for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { if (streamType != streamState.mStreamType && mStreamVolumeAlias[streamType] == streamState.mStreamType) { mStreamStates[streamType].applyDeviceVolume(getDeviceForStream(streamType)); } } // Post a persist volume msg sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, SENDMSG_QUEUE, PERSIST_CURRENT|PERSIST_LAST_AUDIBLE, device, streamState, PERSIST_DELAY); } ... ...
代码很多.上面的消息ID:MSG_SET_FORCE_BT_A2DP_USE,看一下上面Handler里面的:
case MSG_SET_FORCE_USE: case MSG_SET_FORCE_BT_A2DP_USE: setForceUse(msg.arg1, msg.arg2); break;
继续:
private void setForceUse(int usage, int config) { AudioSystem.setForceUse(usage, config); }
继续看AudioSystem.cpp中:
status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; return aps->setForceUse(usage, config); }
上面终于获得的是AudioPolicyService这个服务进行切换设备的.继续看AudioPolicyService.cpp:
status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) { if (mpAudioPolicy == NULL) { return NO_INIT; } if (!settingsAllowed()) { return PERMISSION_DENIED; } if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) { return BAD_VALUE; } if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) { return BAD_VALUE; } ALOGV("setForceUse() tid %d", gettid()); Mutex::Autolock _l(mLock); mpAudioPolicy->set_force_use(mpAudioPolicy, usage, config); return NO_ERROR; }
然后直接对应看audio_policy的HAL层:上面的set_force_use就对应下面的ap_set_force_use(为什么,可以看一下create_audio_policy函数)
/* force using a specific device category for the specified usage */ static void ap_set_force_use(struct audio_policy *pol, audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) { struct legacy_audio_policy *lap = to_lap(pol); lap->apm->setForceUse((AudioSystem::force_use)usage, (AudioSystem::forced_config)config); }
上面apm是什么?
AudioPolicyInterface *apm;
lap->service_client = new AudioPolicyCompatClient(aps_ops, service); if (!lap->service_client) { ret = -ENOMEM; goto err_new_compat_client; } lap->apm = createAudioPolicyManager(lap->service_client);
在上面获取,最后跟踪在AudioPolicyManagerBase.cpp中:
void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
看看下面:
checkA2dpSuspend(); checkOutputForAllStrategies(); updateDevicesAndOutputs(); for (size_t i = 0; i < mOutputs.size(); i++) { audio_io_handle_t output = mOutputs.keyAt(i); audio_devices_t newDevice = getNewDevice(output, true /*fromCache*/); setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE)); if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) { applyStreamVolumes(output, newDevice, 0, true); } }
确认A2DP,后面的是修改策略等,注意下面的恢复A2DP的:
void AudioPolicyManagerBase::checkA2dpSuspend()
到后面的
setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
下面来看看切换流程,假如设备插入耳机:
当耳机插入Android设备,那么与硬件直接打交道的linux核心层内部将会触发uevent或者inputevent事件:
<1> : 如果选择是uevent事件,那么在framework层将直接到WiredAccessoryService,然后给WiredAccessoryManager的notifyChanged处理;
<2> : 如果是inputevent事件,这个就需要先在InputManager中先被捕获,然后再转到WiredAccessoryManager中;
下面直接从notifySwitch开始:
// Native callback. private void notifySwitch(long whenNanos, int switchValues, int switchMask) { if (DEBUG) { Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues) + ", mask=" + Integer.toHexString(switchMask)); } if ((switchMask & SW_LID_BIT) != 0) { final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0); mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen); } if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) { mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues, switchMask); } }
然后转入:
@Override public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) { if (LOG) Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos + " bits=" + switchCodeToString(switchValues, switchMask) + " mask=" + Integer.toHexString(switchMask)); synchronized (mLock) { int headset; mSwitchValues = (mSwitchValues & ~switchMask) | switchValues; switch (mSwitchValues & (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT)) { case 0: headset = 0; break; case SW_HEADPHONE_INSERT_BIT: headset = BIT_HEADSET_NO_MIC; break; case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT: headset = BIT_HEADSET; break; case SW_MICROPHONE_INSERT_BIT: headset = BIT_HEADSET; break; default: headset = 0; break; } updateLocked(NAME_H2W, (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC)) | headset); } }
进入updateLocked
Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, mHeadsetState, newName); mHandler.sendMessage(msg); mHeadsetState = headsetState; } private final Handler mHandler = new Handler(Looper.myLooper(), null, true) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_NEW_DEVICE_STATE: setDevicesState(msg.arg1, msg.arg2, (String)msg.obj); mWakeLock.release(); } } };
看到setdeviceState中 :
private void setDevicesState( int headsetState, int prevHeadsetState, String headsetName) { synchronized (mLock) { int allHeadsets = SUPPORTED_HEADSETS; for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { if ((curHeadset & allHeadsets) != 0) { setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName); allHeadsets &= ~curHeadset; } } } } private void setDeviceStateLocked(int headset, int headsetState, int prevHeadsetState, String headsetName)
在setDeviceStateLocked中继续:
mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
看到这个了,是不是开始看到希望了,AudioManager是连接到AudioService的:
public void setWiredDeviceConnectionState(int device, int state, String name) { IAudioService service = getService(); try { service.setWiredDeviceConnectionState(device, state, name); } catch (RemoteException e) { Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e); } }
这一个转向是不是到了正轨了,下面就是AudioService:
public void setWiredDeviceConnectionState(int device, int state, String name) { synchronized (mConnectedDevices) { int delay = checkSendBecomingNoisyIntent(device, state); queueMsgUnderWakeLock(mAudioHandler, MSG_SET_WIRED_DEVICE_CONNECTION_STATE, device, state, name, delay); } }
一看,又看到mAudioHandler这个handler事件驱动了,上面已经大致介绍了,
case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); mMediaEventWakeLock.release(); break;
继续进入onSetWiredDevice....
handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE, params);
然后进入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(); const char *address = ""; if (aps == 0) return PERMISSION_DENIED; if (device_address != NULL) { address = device_address; } return aps->setDeviceConnectionState(device, state, address); }
看到了吧,终于见到AudioPolicyService了:
status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address) { if (mpAudioPolicy == NULL) { return NO_INIT; } if (!settingsAllowed()) { return PERMISSION_DENIED; } if (!audio_is_output_device(device) && !audio_is_input_device(device)) { return BAD_VALUE; } if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE && state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) { return BAD_VALUE; } ALOGV("setDeviceConnectionState() tid %d", gettid()); Mutex::Autolock _l(mLock); return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device, state, device_address); }
这个AudioPolicyService是打开audio_policy.default.so设备节点,那么就要看这个hal层了:
status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address) { if (mpAudioPolicy == NULL) { return NO_INIT; } if (!settingsAllowed()) { return PERMISSION_DENIED; } if (!audio_is_output_device(device) && !audio_is_input_device(device)) { return BAD_VALUE; } if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE && state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) { return BAD_VALUE; } ALOGV("setDeviceConnectionState() tid %d", gettid()); Mutex::Autolock _l(mLock); return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device, state, device_address); }
再看看里面的set_device_connection_state(...),到audio_hw_hal.cpp中:
对应:
lap->policy.set_device_connection_state = ap_set_device_connection_state;
那么再看看ap_set_device_connection_state函数:
static int ap_set_device_connection_state(struct audio_policy *pol, audio_devices_t device, audio_policy_dev_state_t state, const char *device_address) { struct legacy_audio_policy *lap = to_lap(pol); return lap->apm->setDeviceConnectionState( (AudioSystem::audio_devices)device, (AudioSystem::device_connection_state)state, device_address); }
上面的apm在前面已经大致介绍了,一般是AudioPolicyManagerBase:
status_t AudioPolicyManagerBase::setDeviceConnectionState(audio_devices_t device, AudioSystem::device_connection_state state, const char *device_address)
如果上面不清楚为什么到AudioPolicyManagerBase,可以看一下:
lap->apm = createAudioPolicyManager(lap->service_client);
进入到这个类里面来了,阅读里面的代码,就可以衔接到前面的介绍了.
上面基本上就是整个切换流程,后面看一下蓝牙A2DP