最近遇到一個(gè)問(wèn)題:插入帶麥克風(fēng)的USB攝像頭,攝像頭可以正常輸出圖像但是沒(méi)有聲音,跟蹤了一下整個(gè)框架記錄一下
先從kernel入手:
kernel/sound/usb/card.c
當(dāng)插入U(xiǎn)SB麥克風(fēng),USB Core會(huì)通過(guò)注冊(cè)的usb_audio_ids 匹配到usb_audio_probe()函數(shù)
static struct usb_device_id usb_audio_ids [] = {
#include "quirks-table.h"
? ? { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
????? .bInterfaceClass = USB_CLASS_AUDIO,
? ? ? .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL },
? ? { } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, usb_audio_ids);
/*
* entry point for linux usb interface
*/
static struct usb_driver usb_audio_driver = {
.name = "snd-usb-audio",
.probe = usb_audio_probe,
.disconnect = usb_audio_disconnect,
.suspend = usb_audio_suspend,
.resume = usb_audio_resume,
.id_table = usb_audio_ids,
.supports_autosuspend = 1,
};
static int usb_audio_probe(struct usb_interface *intf,
? const struct usb_device_id *id)
{
struct snd_usb_audio *chip;
chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
if (chip) {
usb_set_intfdata(intf, chip);
return 0;
} else
return -EIO;
}
snd_usb_audio_probe()函數(shù)會(huì)調(diào)用snd_usb_create_quirk()
static struct snd_usb_audio * snd_usb_audio_probe(struct usb_device *dev,struct usb_interface *intf,const struct usb_device_id *usb_id)
{
。。。。。。。。。。。。。。。。。。。
if (!chip->ctrl_intf)
chip->ctrl_intf = alts;
chip->txfr_quirk = 0;
err = 1; /* continue */
if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
/* need some special handlings */
if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
goto __error;
}
if (err > 0) {
/* create normal USB audio interfaces */
if (snd_usb_create_streams(chip, ifnum) < 0 ||
? ? snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) {
goto __error;
}
}
/* we are allowed to call snd_card_register() many times */
if (snd_card_register(chip->card) < 0) {
goto __error;
}
。。。。。。。。。。。。。。。。。。。。。。。。。。
}
int snd_usb_create_quirk(struct snd_usb_audio *chip,struct usb_interface *iface,struct usb_driver *driver,const struct snd_usb_audio_quirk *quirk)
{
typedef int (*quirk_func_t)(struct snd_usb_audio *,
? ? struct usb_interface *,
? ? struct usb_driver *,
? ? const struct snd_usb_audio_quirk *);
static const quirk_func_t quirk_funcs[] = {
[QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
[QUIRK_COMPOSITE] = create_composite_quirk,
[QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
[QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
[QUIRK_MIDI_CME] = create_any_midi_quirk,
[QUIRK_MIDI_AKAI] = create_any_midi_quirk,
[QUIRK_MIDI_FTDI] = create_any_midi_quirk,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
[QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
};
if (quirk->type < QUIRK_TYPE_COUNT) {
return quirk_funcs[quirk->type](chip, iface, driver, quirk);
} else {
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
return -ENXIO;
}
}
static int create_uaxx_quirk(struct snd_usb_audio *chip,
? ? struct usb_interface *iface,
? ? struct usb_driver *driver,
? ? const struct snd_usb_audio_quirk *quirk)
{
。。。。。。
err = snd_usb_add_audio_stream(chip, stream, fp);
。。。。。。
}
int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
? ? int stream,
? ? struct audioformat *fp)
{
err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
? stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
? stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
? &pcm);
}
static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
int playback_count, int capture_count, bool internal,
struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
static struct snd_device_ops ops = {
.dev_free = snd_pcm_dev_free,
.dev_register = snd_pcm_dev_register,
.dev_disconnect = snd_pcm_dev_disconnect,
};
if (snd_BUG_ON(!card))
return -ENXIO;
if (rpcm)
*rpcm = NULL;
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
if (pcm == NULL) {
snd_printk(KERN_ERR "Cannot allocate PCM\n");
return -ENOMEM;
}
pcm->card = card;
pcm->device = device;
pcm->internal = internal;
}
static int snd_pcm_dev_register(struct snd_device *device)
{
int cidx, err;
struct snd_pcm_substream *substream;
struct snd_pcm_notify *notify;
char str[16];
struct snd_pcm *pcm;
struct device *dev;
if (snd_BUG_ON(!device || !device->device_data))
return -ENXIO;
pcm = device->device_data;
mutex_lock(?ister_mutex);
err = snd_pcm_add(pcm);
if (err) {
mutex_unlock(?ister_mutex);
return err;
}
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
if (pcm->streams[cidx].substream == NULL || pcm->internal)
continue;
switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK:
sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
break;
case SNDRV_PCM_STREAM_CAPTURE:
sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
break;
}
/* device pointer to use, pcm->dev takes precedence if
* it is assigned, otherwise fall back to card's device
* if possible */
dev = pcm->dev;
if (!dev)
dev = snd_card_get_device_link(pcm->card);
/* register pcm */
err = snd_register_device_for_dev(devtype, pcm->card,
? pcm->device,
? &snd_pcm_f_ops[cidx],
? pcm, str, dev);
if (err < 0) {
list_del(&pcm->list);
mutex_unlock(?ister_mutex);
return err;
}
snd_add_device_sysfs_file(devtype, pcm->card, pcm->device,
? &pcm_attrs);
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
snd_pcm_timer_init(substream);
}
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_register(pcm);
mutex_unlock(?ister_mutex);
return 0;
}
最終會(huì)在: /dev/snd/pcm*?? 創(chuàng)建出節(jié)點(diǎn)。
進(jìn)入framework/base/services/usb/java/com/android/server/usb/UsbAlsaManager.java
private static final String ALSA_DIRECTORY = "/dev/snd/";
private final FileObserver mAlsaObserver = new FileObserver(ALSA_DIRECTORY,
? ? ? ? ? ? FileObserver.CREATE | FileObserver.DELETE) {
? ? ? ? public void onEvent(int event, String path) {
? ? ? ? ? ? switch (event) {
? ? ? ? ? ? ? ? case FileObserver.CREATE:
? ? ? ? ? ? ? ? ? ? alsaFileAdded(path);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case FileObserver.DELETE:
? ? ? ? ? ? ? ? ? ? alsaFileRemoved(path);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? };
當(dāng)/dev/snd/目錄下有新的設(shè)備節(jié)點(diǎn)創(chuàng)建時(shí)調(diào)用:alsaFileAdded()
private void alsaFileAdded(String name) {
? ? ? ? int type = AlsaDevice.TYPE_UNKNOWN;
? ? ? ? int card = -1, device = -1;
? ? ? ? if (name.startsWith("pcmC")) {
? ? ? ? ? ? if (name.endsWith("p")) {
? ? ? ? ? ? ? ? type = AlsaDevice.TYPE_PLAYBACK;
? ? ? ? ? ? } else if (name.endsWith("c")) {
? ? ? ? ? ? ? ? type = AlsaDevice.TYPE_CAPTURE;
? ? ? ? ? ? }
? ? ? ? } else if (name.startsWith("midiC")) {
? ? ? ? ? ? type = AlsaDevice.TYPE_MIDI;
? ? ? ? }
? ? ? ? if (type != AlsaDevice.TYPE_UNKNOWN) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? int c_index = name.indexOf('C');
? ? ? ? ? ? ? ? int d_index = name.indexOf('D');
? ? ? ? ? ? ? ? int end = name.length();
? ? ? ? ? ? ? ? if (type == AlsaDevice.TYPE_PLAYBACK || type == AlsaDevice.TYPE_CAPTURE) {
? ? ? ? ? ? ? ? ? ? // skip trailing 'p' or 'c'
? ? ? ? ? ? ? ? ? ? end--;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? card = Integer.parseInt(name.substring(c_index + 1, d_index));
? ? ? ? ? ? ? ? device = Integer.parseInt(name.substring(d_index + 1, end));
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? Slog.e(TAG, "Could not parse ALSA file name " + name, e);
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? ? ? synchronized(mAlsaDevices) {
? ? ? ? ? ? ? ? if (mAlsaDevices.get(name) == null) {
? ? ? ? ? ? ? ? ? ? AlsaDevice alsaDevice = new AlsaDevice(type, card, device);
? ? ? ? ? ? ? ? ? ? Slog.d(TAG, "Adding ALSA device " + alsaDevice);
? ? ? ? ? ? ? ? ? ? mAlsaDevices.put(name, alsaDevice);
? ? ? ? ? ? ? ? ? ? mAlsaDevices.notifyAll();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
最后會(huì)調(diào)到:usbDeviceAdded()
void usbDeviceAdded(UsbDevice usbDevice) {
...................................
ArrayList prevScanRecs = mCardsParser.getScanRecords();
mCardsParser.scan();
/*
mCardsParser.scan()的時(shí)候會(huì)讀取聲卡生成記錄系統(tǒng)有多少邏輯設(shè)備的文件:/proc/asound/cards
cat? /proc/asound/cards 信息如下:
?0 [msm8939sndcards]: msm8939-snd-car - msm8939-snd-card-skuk
???????????????????????????????????????????? msm8939-snd-card-skuk
1 [C170? ? ? ? ? ]: USB-Audio - Webcam C170
????????????????????????? Webcam C170 at usb-msm_hsusb_host-1.4.1, high speed
public void scan() {
if (DEBUG) { Slog.i(TAG, "AlsaCardsParser.scan()"); } mCardRecords = new ArrayList();
? ? ? ? File cardsFile = new File(kCardsFilePath); //kCardsFilePath=/proc/asound/cards
? ? ? ? try {
? ? ? ? ? ? FileReader reader = new FileReader(cardsFile);
? ? ? ? ? ? BufferedReader bufferedReader = new BufferedReader(reader);
? ? ? ? ? ? String line = "";
? ? ? ? ? ? while ((line = bufferedReader.readLine()) != null) {
? ? ? ? ? ? ? ? AlsaCardRecord cardRecord = new AlsaCardRecord();
? ? ? ? ? ? ? ? cardRecord.parse(line, 0);
? ? ? ? ? ? ? ? line = bufferedReader.readLine();
? ? ? ? ? ? ? ? if (line == null) {
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? cardRecord.parse(line, 1);
? ? ? ? ? ? ? ? mCardRecords.add(cardRecord);
? ? ? ? ? ? }
? ? ? ? ? ? reader.close();
? ? ? ? } catch (FileNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
*/
..................................
if (mCardsParser.isCardUsb(addedCard)) {
? ? ? ? ? ? UsbAudioDevice audioDevice = selectAudioCard(addedCard);
? ? ? ? ? ? if (audioDevice != null) {
? ? ? ? ? ? ? ? mAudioDevices.put(usbDevice, audioDevice);
? ? ? ? ? ? }
..................................
}
UsbAudioDevice selectAudioCard(int card) {
..................................
notifyDeviceState(audioDevice, true);
...................................
}
private void notifyDeviceState(UsbAudioDevice audioDevice, boolean enabled) {
...........................
// Capture Device
? ? ? ? ? ? if (audioDevice.mHasCapture) {
? ? ? ? ? ? ? int device = (audioDevice == mAccessoryAudioDevice ?
? ? ? ? ? ? ? ? ? ? ? ? AudioSystem.DEVICE_IN_USB_ACCESSORY :
? ? ? ? ? ? ? ? ? ? ? ? AudioSystem.DEVICE_IN_USB_DEVICE);
? ? ? ? ? ? ? ? mAudioService.setWiredDeviceConnectionState(
? ? ? ? ? ? ? ? ? ? ? ? device, state, address, audioDevice.mDeviceName, TAG);
? ? ? ? ? ? }
...........................
}
frameworks/base/services/core/java/com/android/server/audio/AudioService.java
public void setWiredDeviceConnectionState(int type, int state, String address, String name,
? ? ? ? ? ? String caller) {
? ? ? ? synchronized (mConnectedDevices) {
? ? ? ? ? ? int delay = checkSendBecomingNoisyIntent(type, state);
? ? ? ? ? ? queueMsgUnderWakeLock(mAudioHandler,
? ? ? ? ? ? ? ? ? ? MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
? ? ? ? ? ? ? ? ? ? 0,
? ? ? ? ? ? ? ? ? ? 0,
? ? ? ? ? ? ? ? ? ? new WiredDeviceConnectionState(type, state, address, name, caller),
? ? ? ? ? ? ? ? ? ? delay);
? ? ? ? }
? ? }
public void handleMessage(Message msg) {
..............................
case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
? ? ? ? ? ? ? ? ? ? {? WiredDeviceConnectionState connectState =
? ? ? ? ? ? ? ? ? ? ? ? ? ? (WiredDeviceConnectionState)msg.obj;
? ? ? ? ? ? ? ? ? ? ? ? onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? connectState.mAddress, connectState.mName, connectState.mCaller);
? ? ? ? ? ? ? ? ? ? ? ? mAudioEventWakeLock.release();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
..............................
}
private void onSetWiredDeviceConnectionState(int device, int state, String address,
? ? ? ? ? ? String deviceName, String caller) {
.............................................................
boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) ||
? ? ? ? ? ? ? ? ? ? ? ? ? ? (((device & AudioSystem.DEVICE_BIT_IN) != 0) &&
? ? ? ? ? ? ? ? ? ? ? ? ? ? ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0));
? ? ? ? ? ? if (!handleDeviceConnection(state == 1, device, address, deviceName)) {
? ? ? ? ? ? ? ? // change of connection state failed, bailout
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
............................................................
}
private boolean handleDeviceConnection(boolean connect, int device, String address,
? ? ? ? ? ? String deviceName) {
........................................
if (connect && !isConnected) {//第一次連接走這里
? ? ? ? ? ? ? ? final int res = AudioSystem.setDeviceConnectionState(device,
? ? ? ? ? ? ? ? ? ? ? ? AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName);
? ? ? ? ? ? ? ? if (res != AudioSystem.AUDIO_STATUS_OK) {
? ? ? ? ? ? ? ? ? ? Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device) +
? ? ? ? ? ? ? ? ? ? ? ? ? ? " due to command error " + res );
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? mConnectedDevices.put(deviceKey, new DeviceListSpec(device, deviceName, address));
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? } else if (!connect && isConnected) {//斷開(kāi)走這里
? ? ? ? ? ? ? ? AudioSystem.setDeviceConnectionState(device,
? ? ? ? ? ? ? ? ? ? ? ? AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName);
? ? ? ? ? ? ? ? // always remove even if disconnection failed
? ? ? ? ? ? ? ? mConnectedDevices.remove(deviceKey);
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
..........................................
}
frameworks/base/media/java/android/media/AudioSystem.java
public static native int setDeviceConnectionState(int device, int state,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String device_address, String device_name);
通過(guò)JNI調(diào)到:frameworks/base/core/jni/android_media_AudioSystem.cpp
static jintandroid_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name){ const char *c_address = env->GetStringUTFChars(device_address, NULL); const char *c_name = env->GetStringUTFChars(device_name, NULL); int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast(device), static_cast(state),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? c_address, c_name));
? ? env->ReleaseStringUTFChars(device_address, c_address);
? ? env->ReleaseStringUTFChars(device_name, c_name);
? ? return (jint) status;
}
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 char *device_name){ const sp& aps = AudioSystem::get_audio_policy_service();
? ? const char *address = "";
? ? const char *name = "";
? ? if (aps == 0) return PERMISSION_DENIED;
? ? if (device_address != NULL) {
? ? ? ? address = device_address;
? ? }
? ? if (device_name != NULL) {
? ? ? ? name = device_name;
? ? }
? ? return aps->setDeviceConnectionState(device, state, address, name);
}
最終調(diào)到:
hardware\qcom\audio\policy_hal\AudioPolicyManager.cpp
status_t AudioPolicyManagerCustom::setDeviceConnectionStateInt(audio_devices_t device,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_policy_dev_state_t state,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const char *device_address,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const char *device_name)
{
..........................................................
// handle input devices if (audio_is_input_device(device)) { SortedVectorinputs; ssize_t index = mAvailableInputDevices.indexOf(devDesc); switch (state) { // handle input device connection case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: { if (index >= 0) { ALOGW("setDeviceConnectionState() device already connected: %d", device); return INVALID_OPERATION; } sp module = mHwModules.getModuleForDevice(device);
? ? ? ? ? ? if (module == NULL) {
? ? ? ? ? ? ? ? ALOGW("setDeviceConnectionState(): could not find HW module for device %08x",
? ? ? ? ? ? ? ? ? ? ? device);
? ? ? ? ? ? ? ? return INVALID_OPERATION;
? ? ? ? ? ? }
? ? ? ? ? ? if (checkInputsForDevice(devDesc, state, inputs, devDesc->mAddress) != NO_ERROR) {
? ? ? ? ? ? ? ? return INVALID_OPERATION;
? ? ? ? ? ? }
? ? ? ? ? ? index = mAvailableInputDevices.add(devDesc);//添加到可用輸入設(shè)備列表中待選
? ? ? ? ? ? if (index >= 0) {
? ? ? ? ? ? ? ? mAvailableInputDevices[index]->attach(module);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return NO_MEMORY;
? ? ? ? ? ? }
? ? ? ? ? ? // Set connect to HALs
? ? ? ? ? ? AudioParameter param = AudioParameter(devDesc->mAddress);
? ? ? ? ? ? param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
? ? ? ? ? ? mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
? ? ? ? ? ? // Propagate device availability to Engine
? ? ? ? ? ? mEngine->setDeviceConnectionState(devDesc, state);
? ? ? ? } break;
..........................................................
}
沒(méi)有插入U(xiǎn)SB麥克風(fēng)是輸入設(shè)備列表LOG如下:
APM::Devices: Device id:5 type:0x80000004:Built-In Mic, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:6 type:0x80000080:Built-In Back Mic, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:9 type:0x80000100:Reroute Submix In, addr:0
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:7 type:0x80000040:Telephony Rx, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:8 type:0x80002000:FM Tuner In, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
當(dāng)插入U(xiǎn)SB麥克風(fēng)是輸入設(shè)備列表LOG如下:
APM::Devices: Device id:5 type:0x80000004:Built-In Mic, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:6 type:0x80000080:Built-In Back Mic, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:9 type:0x80000100:Reroute Submix In, addr:0
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:7 type:0x80000040:Telephony Rx, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:8 type:0x80002000:FM Tuner In, addr:
APM::AudioPort:? ? Port[nm:, type:1, role:1]
APM::Devices: Device id:13 type:0x80001000:USB Device In, addr:card=1;device=0;
APM::AudioPort: Port[nm:USB-Audio - Webcam C170, type:1, role:1]
-----------------------------------------------------------------------------------------------------------------------
當(dāng)APP通過(guò):audioRecord =new AudioRecord(MediaRecorder.AudioSource.MIC, frequency,
? ? ? ? channelConfiguration, audioEncoding, recBufSize);
???????? audioRecord.startRecording();
最終會(huì)轉(zhuǎn)到
status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_io_handle_t *input,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_session_t session,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uid_t uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uint32_t samplingRate,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_format_t format,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_channel_mask_t channelMask,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_input_flags_t flags,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_port_handle_t selectedDeviceId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? input_type_t *inputType)
{
。。。。。。。。。。。。。。。
//根據(jù)輸入源類(lèi)型我們?cè)赼pp中選擇的是inputSource=MediaRecorder.AudioSource.MIC
device = getDeviceAndMixForInputSource(inputSource, &policyMix);
。。。。。。。
}
audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource,AudioMix **policyMix)
{
? ? audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
? ? audio_devices_t selectedDeviceFromMix =
? ? ? ? ? mPolicyMixes.getDeviceAndMixForInputSource(inputSource, availableDeviceTypes, policyMix);
? ? if (selectedDeviceFromMix != AUDIO_DEVICE_NONE) {
? ? ? ? return selectedDeviceFromMix;
? ? }
? ? return getDeviceForInputSource(inputSource);
}
audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource){ for (size_t routeIndex = 0; routeIndex < mInputRoutes.size(); routeIndex++) { sp route = mInputRoutes.valueAt(routeIndex);
? ? ? ? if (inputSource == route->mSource && route->isActive()) {
? ? ? ? ? ? return route->mDeviceDescriptor->type();
? ? ? ? }
? ? }
? ? return mEngine->getDeviceForInputSource(inputSource);
}
audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
{
。。。。。。。。。。。
switch (inputSource) {
? ? case AUDIO_SOURCE_VOICE_UPLINK:
? ? ? if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
? ? ? ? ? device = AUDIO_DEVICE_IN_VOICE_CALL;
? ? ? ? ? break;
? ? ? }
? ? ? break;
? ? case AUDIO_SOURCE_DEFAULT:
? ? case AUDIO_SOURCE_MIC:
? ? if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
? ? ? ? device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
? ? } else if ((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO) &&
? ? ? ? (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
? ? ? ? device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
? ? } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
? ? ? ? device = AUDIO_DEVICE_IN_WIRED_HEADSET;
? ? } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
? ? ? ? device = AUDIO_DEVICE_IN_USB_DEVICE;
? ? } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
? ? ? ? device = AUDIO_DEVICE_IN_BUILTIN_MIC;
? ? }
? ? break;
。。。。。。。。
}
從次可以看出系統(tǒng)選擇麥克風(fēng)的優(yōu)先順序