Android6.0----關(guān)于USB麥克風(fēng)框架

最近遇到一個(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)先順序

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容