首先audioflinger创建音频hw类-比如alsa类,如果打开了with_a2dp编译选项,那么随后a2dpaudiointerface类将作为audioflinger最终使用的hw类,[luther.gliethttp]如果打开一个device,将调用a2dpaudiointerface::openoutputstream,如果该device不是a2dp设备,那么a2dpaudiointerface类将直接调用alsa类提供的函数openoutputstream打开实际的alsa设备,可见android系统a2dp功能根本就用不到alsa的任何东西,即便audio驱动没有完成a2dp仍然可独立使用[luther.gliethttp].对于media等音频的发送,首先是由audioflinger将通过借助binder采用ashmem共享文件方式推入数据的各个track进行mixer,所有mixer后的最终pcm数据将被推入moutput->write(curbuf, mixbuffersize);也就是a2dpaudiointerface::a2dpaudiostreamout::write(const void* buffer, size_t bytes);随后这些裸pcm数据将被送入bluez的a2dp_write(mdata, buffer, remaining);进行sbc_encode即sbc编码,透过socket或者rfcomm送到bluetooth chip芯片最后发送到air等待a2dp设备接收.[luther.gliethttp]audiohardwareinterface* audiohardwareinterface::create(){ ...... hw = createaudiohardware(); // 调用alsa_sound/audiohardwarealsa.cpp构造函数 ......#ifdef with_a2dp hw = new a2dpaudiointerface(hw); // 使用a2dp作为默认hw,这样a2dp这个hw类发现device不是a2dp时#endif // 它会调用alsa的hw打开设备,否则将自己打开该a2dp device[luther.gliethttp] ...... return hw;}audiostreamout* a2dpaudiointerface::openoutputstream( uint32_t devices, int *format, uint32_t *channels, uint32_t *samplerate, status_t *status){ if (!audiosystem::isa2dpdevice((audiosystem::audio_devices)devices)) { logv("a2dpaudiointerface::openoutputstream() open hw device: %x", devices); return mhardwareinterface->openoutputstream(devices, format, channels, samplerate, status); } status_t err = 0; // only one output stream allowed if (moutput) { if (status) *status = -1; return null; } // create new output stream a2dpaudiostreamout* out = new a2dpaudiostreamout(); if ((err = out->set(devices, format, channels, samplerate)) == no_error) { moutput = out; moutput->setbluetoothenabled(mbluetoothenabled); moutput->setsuspended(msuspended); } else { delete out; } if (status) *status = err; return moutput;}frameworks/base/libs/audioflinger/a2dpaudiointerface.cpp==> a2dpaudiointerface::a2dpaudiostreamout::init==> 调用external/bluetooth/bluez/audio/liba2dp.c中的==> a2dp_init(44100, 2, &mdata);ssize_t a2dpaudiointerface::a2dpaudiostreamout::write(const void* buffer, size_t bytes){ mutex::autolock lock(mlock); size_t remaining = bytes; status_t status = -1; if (!mbluetoothenabled || mclosing || msuspended) { logv("a2dpaudiostreamout::write(), but bluetooth disabled / mbluetoothenabled %d, mclosing %d, msuspended %d", mbluetoothenabled, mclosing, msuspended); goto error; } status = init(); if (status < 0) goto error; while (remaining > 0) { status = a2dp_write(mdata, buffer, remaining); if (status <= 0) { loge("a2dp_write failed err: %d/n", status); goto error; } remaining -= status; buffer = ((char *)buffer) + status; } mstandby = false; return bytes;error: // simulate audio output timing in case of error usleep(((bytes * 1000 )/ framesize() / samplerate()) * 1000); return status;}int a2dp_write(a2dpdata d, const void* buffer, int count){ struct bluetooth_data* data = (struct bluetooth_data*)d; uint8_t* src = (uint8_t *)buffer; int codesize; int err, ret = 0; long frames_left = count; int encoded; unsigned int written; const char *buff; int did_configure = 0;#ifdef enable_timing uint64_t begin, end; dbg("********** a2dp_write **********"); begin = get_microseconds();#endif err = wait_for_start(data, write_timeout); if (err < 0) return err; codesize = data->codesize; while (frames_left >= codesize) { /* enough data to encode (sbc wants 512 byte blocks) */ encoded = sbc_encode(&(data->sbc), src, codesize, data->buffer + data->count, sizeof(data->buffer) - data->count, &written); if (encoded <= 0) { err("encoding error %d", encoded); goto done; } vdbg("sbc_encode returned %d, codesize: %d, written: %d/n", encoded, codesize, written); src += encoded; data->count += written; data->frame_count++; data->samples += encoded; data->nsamples += encoded; /* no space left for another frame then send */ if ((data->count + written >= data->link_mtu) || (data->count + written >= buffer_size)) { vdbg("sending packet %d, count %d, link_mtu %u", data->seq_num, data->count, data->link_mtu); err = avdtp_write(data); if (err < 0) return err; } ret += encoded; frames_left -= encoded; } if (frames_left > 0) err("%ld bytes left at end of a2dp_write/n", frames_left);done:#ifdef enable_timing end = get_microseconds(); print_time("a2dp_write total", begin, end);#endif return ret;}
