Loading include/private/media/AudioTrackShared.h +7 −7 Original line number Diff line number Diff line Loading @@ -175,12 +175,11 @@ protected: // Proxy seen by AudioTrack client and AudioRecord client class ClientProxy : public Proxy { protected: public: ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, bool clientInServer); virtual ~ClientProxy() { } public: static const struct timespec kForever; static const struct timespec kNonBlocking; Loading Loading @@ -394,8 +393,10 @@ protected: class AudioTrackServerProxy : public ServerProxy { public: AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool clientInServer = false) : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) { } size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0) : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) { mCblk->mSampleRate = sampleRate; } protected: virtual ~AudioTrackServerProxy() { } Loading Loading @@ -458,9 +459,8 @@ private: class AudioRecordServerProxy : public ServerProxy { public: AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, false /*clientInServer*/) { } size_t frameSize, bool clientInServer) : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { } protected: virtual ~AudioRecordServerProxy() { } }; Loading services/audioflinger/AudioFlinger.cpp +140 −87 Original line number Diff line number Diff line Loading @@ -1531,7 +1531,7 @@ audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name) } audio_module_handle_t handle = nextUniqueId(); mAudioHwDevs.add(handle, new AudioHwDevice(name, dev, flags)); mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags)); ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d", name, dev->common.module->name, dev->common.module->id, handle); Loading Loading @@ -1575,41 +1575,13 @@ status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice) // ---------------------------------------------------------------------------- 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, const audio_offload_info_t *offloadInfo) { struct audio_config config; memset(&config, 0, sizeof(config)); config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0; config.channel_mask = (pChannelMask != NULL) ? *pChannelMask : 0; config.format = (pFormat != NULL) ? *pFormat : AUDIO_FORMAT_DEFAULT; if (offloadInfo != NULL) { config.offload_info = *offloadInfo; } ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x", module, (pDevices != NULL) ? *pDevices : 0, config.sample_rate, config.format, config.channel_mask, flags); ALOGV("openOutput(), offloadInfo %p version 0x%04x", offloadInfo, offloadInfo == NULL ? -1 : offloadInfo->version); if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return AUDIO_IO_HANDLE_NONE; } Mutex::Autolock _l(mLock); AudioHwDevice *outHwDev = findSuitableHwDev_l(module, *pDevices); sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_output_flags_t flags) { AudioHwDevice *outHwDev = findSuitableHwDev_l(module, device); if (outHwDev == NULL) { return AUDIO_IO_HANDLE_NONE; } Loading @@ -1635,18 +1607,18 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, status_t status = hwDevHal->open_output_stream(hwDevHal, id, *pDevices, (audio_output_flags_t)flags, &config, device, flags, config, &outStream); mHardwareStatus = AUDIO_HW_IDLE; ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %#08x, " ALOGV("openOutput_l() openOutputStream returned output %p, SamplingRate %d, Format %#08x, " "Channels %x, status %d", outStream, config.sample_rate, config.format, config.channel_mask, config->sample_rate, config->format, config->channel_mask, status); if (status == NO_ERROR && outStream != NULL) { Loading @@ -1654,19 +1626,60 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, PlaybackThread *thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { thread = new OffloadThread(this, output, id, *pDevices); thread = new OffloadThread(this, output, id, device); ALOGV("openOutput() created offload output: ID %d thread %p", id, thread); } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config.format) || (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output, id, *pDevices); || !isValidPcmSinkFormat(config->format) || (config->channel_mask != AUDIO_CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output, id, device); ALOGV("openOutput() created direct output: ID %d thread %p", id, thread); } else { thread = new MixerThread(this, output, id, *pDevices); thread = new MixerThread(this, output, id, device); ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread); } mPlaybackThreads.add(id, thread); return thread; } return 0; } 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, const audio_offload_info_t *offloadInfo) { struct audio_config config; memset(&config, 0, sizeof(config)); config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0; config.channel_mask = (pChannelMask != NULL) ? *pChannelMask : 0; config.format = (pFormat != NULL) ? *pFormat : AUDIO_FORMAT_DEFAULT; if (offloadInfo != NULL) { config.offload_info = *offloadInfo; } ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x", module, (pDevices != NULL) ? *pDevices : 0, config.sample_rate, config.format, config.channel_mask, flags); ALOGV("openOutput(), offloadInfo %p version 0x%04x", offloadInfo, offloadInfo == NULL ? -1 : offloadInfo->version); if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return AUDIO_IO_HANDLE_NONE; } Mutex::Autolock _l(mLock); sp<PlaybackThread> thread = openOutput_l(module, *pDevices, &config, flags); if (thread != 0) { if (pSamplingRate != NULL) { *pSamplingRate = config.sample_rate; } Loading @@ -1686,16 +1699,16 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, // the first primary output opened designates the primary hw device if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) { ALOGI("Using module %d has the primary audio interface", module); mPrimaryHardwareDev = outHwDev; mPrimaryHardwareDev = thread->getOutput()->audioHwDev; AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MODE; hwDevHal->set_mode(hwDevHal, mMode); mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode); mHardwareStatus = AUDIO_HW_IDLE; mPrimaryOutputSampleRate = config.sample_rate; } return id; return thread->id(); } return AUDIO_IO_HANDLE_NONE; Loading Loading @@ -1776,13 +1789,27 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output) // but the ThreadBase container still exists. if (thread->type() != ThreadBase::DUPLICATING) { closeOutputFinish(thread); } thread.clear(); return NO_ERROR; } void AudioFlinger::closeOutputFinish(sp<PlaybackThread> thread) { AudioStreamOut *out = thread->clearOutput(); ALOG_ASSERT(out != NULL, "out shouldn't be NULL"); // from now on thread->mOutput is NULL out->hwDev()->close_output_stream(out->hwDev(), out->stream); delete out; } return NO_ERROR; void AudioFlinger::closeOutputInternal_l(sp<PlaybackThread> thread) { mPlaybackThreads.removeItem(thread->mId); thread->exit(); closeOutputFinish(thread); } status_t AudioFlinger::suspendOutput(audio_io_handle_t output) Loading Loading @@ -1823,6 +1850,12 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, audio_channel_mask_t *pChannelMask, audio_input_flags_t flags) { Mutex::Autolock _l(mLock); if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return AUDIO_IO_HANDLE_NONE; } struct audio_config config; memset(&config, 0, sizeof(config)); config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0; Loading @@ -1833,13 +1866,36 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, audio_format_t reqFormat = config.format; audio_channel_mask_t reqChannelMask = config.channel_mask; if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return 0; sp<RecordThread> thread = openInput_l(module, *pDevices, &config, flags); if (thread != 0) { if (pSamplingRate != NULL) { *pSamplingRate = reqSamplingRate; } if (pFormat != NULL) { *pFormat = config.format; } if (pChannelMask != NULL) { *pChannelMask = reqChannelMask; } Mutex::Autolock _l(mLock); // notify client processes of the new input creation thread->audioConfigChanged(AudioSystem::INPUT_OPENED); return thread->id(); } return AUDIO_IO_HANDLE_NONE; } AudioHwDevice *inHwDev = findSuitableHwDev_l(module, *pDevices); sp<AudioFlinger::RecordThread> AudioFlinger::openInput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_input_flags_t flags) { uint32_t reqSamplingRate = config->sample_rate; audio_format_t reqFormat = config->format; audio_channel_mask_t reqChannelMask = config->channel_mask; AudioHwDevice *inHwDev = findSuitableHwDev_l(module, device); if (inHwDev == NULL) { return 0; } Loading @@ -1848,14 +1904,14 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, audio_io_handle_t id = nextUniqueId(); audio_stream_in_t *inStream = NULL; status_t status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, status_t status = inHwHal->open_input_stream(inHwHal, id, device, config, &inStream, flags); ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %#x, Channels %x, " "flags %#x, status %d", inStream, config.sample_rate, config.format, config.channel_mask, config->sample_rate, config->format, config->channel_mask, flags, status); Loading @@ -1863,14 +1919,14 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, // conversion internally, try to open again with the proposed parameters. The AudioFlinger can // resample the input and do mono to stereo or stereo to mono conversions on 16 bit PCM inputs. if (status == BAD_VALUE && reqFormat == config.format && config.format == AUDIO_FORMAT_PCM_16_BIT && (config.sample_rate <= 2 * reqSamplingRate) && (audio_channel_count_from_in_mask(config.channel_mask) <= FCC_2) && reqFormat == config->format && config->format == AUDIO_FORMAT_PCM_16_BIT && (config->sample_rate <= 2 * reqSamplingRate) && (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_2) && (audio_channel_count_from_in_mask(reqChannelMask) <= FCC_2)) { // FIXME describe the change proposed by HAL (save old values so we can log them here) ALOGV("openInput() reopening with proposed sampling rate and channel mask"); inStream = NULL; status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, &inStream, flags); status = inHwHal->open_input_stream(inHwHal, id, device, config, &inStream, flags); // FIXME log this new status; HAL should not propose any further changes } Loading Loading @@ -1931,30 +1987,18 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, // Start record thread // RecordThread requires both input and output device indication to forward to audio // pre processing modules RecordThread *thread = new RecordThread(this, sp<RecordThread> thread = new RecordThread(this, input, id, primaryOutputDevice_l(), *pDevices device #ifdef TEE_SINK , teeSink #endif ); mRecordThreads.add(id, thread); ALOGV("openInput() created record thread: ID %d thread %p", id, thread); if (pSamplingRate != NULL) { *pSamplingRate = reqSamplingRate; } if (pFormat != NULL) { *pFormat = config.format; } if (pChannelMask != NULL) { *pChannelMask = reqChannelMask; } // notify client processes of the new input creation thread->audioConfigChanged(AudioSystem::INPUT_OPENED); return id; ALOGV("openInput() created record thread: ID %d thread %p", id, thread.get()); return thread; } return 0; Loading @@ -1981,17 +2025,26 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input) audioConfigChanged(AudioSystem::INPUT_CLOSED, input, NULL); mRecordThreads.removeItem(input); } thread->exit(); // The thread entity (active unit of execution) is no longer running here, // but the ThreadBase container still exists. // FIXME: calling thread->exit() without mLock held should not be needed anymore now that // we have a different lock for notification client closeInputFinish(thread); return NO_ERROR; } void AudioFlinger::closeInputFinish(sp<RecordThread> thread) { thread->exit(); AudioStreamIn *in = thread->clearInput(); ALOG_ASSERT(in != NULL, "in shouldn't be NULL"); // from now on thread->mInput is NULL in->hwDev()->close_input_stream(in->hwDev(), in->stream); delete in; } return NO_ERROR; void AudioFlinger::closeInputInternal_l(sp<RecordThread> thread) { mRecordThreads.removeItem(thread->mId); closeInputFinish(thread); } status_t AudioFlinger::invalidateStream(audio_stream_type_t stream) Loading services/audioflinger/AudioFlinger.h +19 −2 Original line number Diff line number Diff line Loading @@ -489,6 +489,18 @@ private: PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const; MixerThread *checkMixerThread_l(audio_io_handle_t output) const; RecordThread *checkRecordThread_l(audio_io_handle_t input) const; sp<RecordThread> openInput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_input_flags_t flags); sp<PlaybackThread> openOutput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_output_flags_t flags); void closeOutputFinish(sp<PlaybackThread> thread); void closeInputFinish(sp<RecordThread> thread); // no range check, AudioFlinger::mLock held bool streamMute_l(audio_stream_type_t stream) const { return mStreamTypes[stream].mute; } Loading Loading @@ -530,10 +542,11 @@ private: AHWD_CAN_SET_MASTER_MUTE = 0x2, }; AudioHwDevice(const char *moduleName, AudioHwDevice(audio_module_handle_t handle, const char *moduleName, audio_hw_device_t *hwDevice, Flags flags) : mModuleName(strdup(moduleName)) : mHandle(handle), mModuleName(strdup(moduleName)) , mHwDevice(hwDevice) , mFlags(flags) { } /*virtual*/ ~AudioHwDevice() { free((void *)mModuleName); } Loading @@ -546,11 +559,13 @@ private: return (0 != (mFlags & AHWD_CAN_SET_MASTER_MUTE)); } audio_module_handle_t handle() const { return mHandle; } const char *moduleName() const { return mModuleName; } audio_hw_device_t *hwDevice() const { return mHwDevice; } uint32_t version() const { return mHwDevice->common.version; } private: audio_module_handle_t mHandle; const char * const mModuleName; audio_hw_device_t * const mHwDevice; const Flags mFlags; Loading Loading @@ -669,7 +684,9 @@ private: // for use from destructor status_t closeOutput_nonvirtual(audio_io_handle_t output); void closeOutputInternal_l(sp<PlaybackThread> thread); status_t closeInput_nonvirtual(audio_io_handle_t input); void closeInputInternal_l(sp<RecordThread> thread); #ifdef TEE_SINK // all record threads serially share a common tee sink, which is re-created on format change Loading services/audioflinger/PatchPanel.cpp +288 −64 File changed.Preview size limit exceeded, changes collapsed. Show changes services/audioflinger/PatchPanel.h +24 −6 Original line number Diff line number Diff line Loading @@ -21,6 +21,9 @@ class PatchPanel : public RefBase { public: class Patch; PatchPanel(const sp<AudioFlinger>& audioFlinger); virtual ~PatchPanel(); Loading @@ -45,15 +48,30 @@ public: /* Set audio port configuration */ status_t setAudioPortConfig(const struct audio_port_config *config); status_t createPatchConnections(Patch *patch, const struct audio_patch *audioPatch); void clearPatchConnections(Patch *patch); class Patch { public: Patch(const struct audio_patch *patch) : mAudioPatch(*patch), mHandle(0), mHalHandle(0) {} mAudioPatch(*patch), mHandle(AUDIO_PATCH_HANDLE_NONE), mHalHandle(AUDIO_PATCH_HANDLE_NONE), mRecordPatchHandle(AUDIO_PATCH_HANDLE_NONE), mPlaybackPatchHandle(AUDIO_PATCH_HANDLE_NONE) {} ~Patch() {} struct audio_patch mAudioPatch; audio_patch_handle_t mHandle; audio_patch_handle_t mHalHandle; sp<PlaybackThread> mPlaybackThread; sp<PlaybackThread::PatchTrack> mPatchTrack; sp<RecordThread> mRecordThread; sp<RecordThread::PatchRecord> mPatchRecord; audio_patch_handle_t mRecordPatchHandle; audio_patch_handle_t mPlaybackPatchHandle; }; private: const wp<AudioFlinger> mAudioFlinger; SortedVector <Patch *> mPatches; Loading Loading
include/private/media/AudioTrackShared.h +7 −7 Original line number Diff line number Diff line Loading @@ -175,12 +175,11 @@ protected: // Proxy seen by AudioTrack client and AudioRecord client class ClientProxy : public Proxy { protected: public: ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, bool clientInServer); virtual ~ClientProxy() { } public: static const struct timespec kForever; static const struct timespec kNonBlocking; Loading Loading @@ -394,8 +393,10 @@ protected: class AudioTrackServerProxy : public ServerProxy { public: AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool clientInServer = false) : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) { } size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0) : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) { mCblk->mSampleRate = sampleRate; } protected: virtual ~AudioTrackServerProxy() { } Loading Loading @@ -458,9 +459,8 @@ private: class AudioRecordServerProxy : public ServerProxy { public: AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, false /*clientInServer*/) { } size_t frameSize, bool clientInServer) : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { } protected: virtual ~AudioRecordServerProxy() { } }; Loading
services/audioflinger/AudioFlinger.cpp +140 −87 Original line number Diff line number Diff line Loading @@ -1531,7 +1531,7 @@ audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name) } audio_module_handle_t handle = nextUniqueId(); mAudioHwDevs.add(handle, new AudioHwDevice(name, dev, flags)); mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags)); ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d", name, dev->common.module->name, dev->common.module->id, handle); Loading Loading @@ -1575,41 +1575,13 @@ status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice) // ---------------------------------------------------------------------------- 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, const audio_offload_info_t *offloadInfo) { struct audio_config config; memset(&config, 0, sizeof(config)); config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0; config.channel_mask = (pChannelMask != NULL) ? *pChannelMask : 0; config.format = (pFormat != NULL) ? *pFormat : AUDIO_FORMAT_DEFAULT; if (offloadInfo != NULL) { config.offload_info = *offloadInfo; } ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x", module, (pDevices != NULL) ? *pDevices : 0, config.sample_rate, config.format, config.channel_mask, flags); ALOGV("openOutput(), offloadInfo %p version 0x%04x", offloadInfo, offloadInfo == NULL ? -1 : offloadInfo->version); if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return AUDIO_IO_HANDLE_NONE; } Mutex::Autolock _l(mLock); AudioHwDevice *outHwDev = findSuitableHwDev_l(module, *pDevices); sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_output_flags_t flags) { AudioHwDevice *outHwDev = findSuitableHwDev_l(module, device); if (outHwDev == NULL) { return AUDIO_IO_HANDLE_NONE; } Loading @@ -1635,18 +1607,18 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, status_t status = hwDevHal->open_output_stream(hwDevHal, id, *pDevices, (audio_output_flags_t)flags, &config, device, flags, config, &outStream); mHardwareStatus = AUDIO_HW_IDLE; ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %#08x, " ALOGV("openOutput_l() openOutputStream returned output %p, SamplingRate %d, Format %#08x, " "Channels %x, status %d", outStream, config.sample_rate, config.format, config.channel_mask, config->sample_rate, config->format, config->channel_mask, status); if (status == NO_ERROR && outStream != NULL) { Loading @@ -1654,19 +1626,60 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, PlaybackThread *thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { thread = new OffloadThread(this, output, id, *pDevices); thread = new OffloadThread(this, output, id, device); ALOGV("openOutput() created offload output: ID %d thread %p", id, thread); } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config.format) || (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output, id, *pDevices); || !isValidPcmSinkFormat(config->format) || (config->channel_mask != AUDIO_CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output, id, device); ALOGV("openOutput() created direct output: ID %d thread %p", id, thread); } else { thread = new MixerThread(this, output, id, *pDevices); thread = new MixerThread(this, output, id, device); ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread); } mPlaybackThreads.add(id, thread); return thread; } return 0; } 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, const audio_offload_info_t *offloadInfo) { struct audio_config config; memset(&config, 0, sizeof(config)); config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0; config.channel_mask = (pChannelMask != NULL) ? *pChannelMask : 0; config.format = (pFormat != NULL) ? *pFormat : AUDIO_FORMAT_DEFAULT; if (offloadInfo != NULL) { config.offload_info = *offloadInfo; } ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x", module, (pDevices != NULL) ? *pDevices : 0, config.sample_rate, config.format, config.channel_mask, flags); ALOGV("openOutput(), offloadInfo %p version 0x%04x", offloadInfo, offloadInfo == NULL ? -1 : offloadInfo->version); if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return AUDIO_IO_HANDLE_NONE; } Mutex::Autolock _l(mLock); sp<PlaybackThread> thread = openOutput_l(module, *pDevices, &config, flags); if (thread != 0) { if (pSamplingRate != NULL) { *pSamplingRate = config.sample_rate; } Loading @@ -1686,16 +1699,16 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, // the first primary output opened designates the primary hw device if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) { ALOGI("Using module %d has the primary audio interface", module); mPrimaryHardwareDev = outHwDev; mPrimaryHardwareDev = thread->getOutput()->audioHwDev; AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MODE; hwDevHal->set_mode(hwDevHal, mMode); mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode); mHardwareStatus = AUDIO_HW_IDLE; mPrimaryOutputSampleRate = config.sample_rate; } return id; return thread->id(); } return AUDIO_IO_HANDLE_NONE; Loading Loading @@ -1776,13 +1789,27 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output) // but the ThreadBase container still exists. if (thread->type() != ThreadBase::DUPLICATING) { closeOutputFinish(thread); } thread.clear(); return NO_ERROR; } void AudioFlinger::closeOutputFinish(sp<PlaybackThread> thread) { AudioStreamOut *out = thread->clearOutput(); ALOG_ASSERT(out != NULL, "out shouldn't be NULL"); // from now on thread->mOutput is NULL out->hwDev()->close_output_stream(out->hwDev(), out->stream); delete out; } return NO_ERROR; void AudioFlinger::closeOutputInternal_l(sp<PlaybackThread> thread) { mPlaybackThreads.removeItem(thread->mId); thread->exit(); closeOutputFinish(thread); } status_t AudioFlinger::suspendOutput(audio_io_handle_t output) Loading Loading @@ -1823,6 +1850,12 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, audio_channel_mask_t *pChannelMask, audio_input_flags_t flags) { Mutex::Autolock _l(mLock); if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return AUDIO_IO_HANDLE_NONE; } struct audio_config config; memset(&config, 0, sizeof(config)); config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0; Loading @@ -1833,13 +1866,36 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, audio_format_t reqFormat = config.format; audio_channel_mask_t reqChannelMask = config.channel_mask; if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) { return 0; sp<RecordThread> thread = openInput_l(module, *pDevices, &config, flags); if (thread != 0) { if (pSamplingRate != NULL) { *pSamplingRate = reqSamplingRate; } if (pFormat != NULL) { *pFormat = config.format; } if (pChannelMask != NULL) { *pChannelMask = reqChannelMask; } Mutex::Autolock _l(mLock); // notify client processes of the new input creation thread->audioConfigChanged(AudioSystem::INPUT_OPENED); return thread->id(); } return AUDIO_IO_HANDLE_NONE; } AudioHwDevice *inHwDev = findSuitableHwDev_l(module, *pDevices); sp<AudioFlinger::RecordThread> AudioFlinger::openInput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_input_flags_t flags) { uint32_t reqSamplingRate = config->sample_rate; audio_format_t reqFormat = config->format; audio_channel_mask_t reqChannelMask = config->channel_mask; AudioHwDevice *inHwDev = findSuitableHwDev_l(module, device); if (inHwDev == NULL) { return 0; } Loading @@ -1848,14 +1904,14 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, audio_io_handle_t id = nextUniqueId(); audio_stream_in_t *inStream = NULL; status_t status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, status_t status = inHwHal->open_input_stream(inHwHal, id, device, config, &inStream, flags); ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %#x, Channels %x, " "flags %#x, status %d", inStream, config.sample_rate, config.format, config.channel_mask, config->sample_rate, config->format, config->channel_mask, flags, status); Loading @@ -1863,14 +1919,14 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, // conversion internally, try to open again with the proposed parameters. The AudioFlinger can // resample the input and do mono to stereo or stereo to mono conversions on 16 bit PCM inputs. if (status == BAD_VALUE && reqFormat == config.format && config.format == AUDIO_FORMAT_PCM_16_BIT && (config.sample_rate <= 2 * reqSamplingRate) && (audio_channel_count_from_in_mask(config.channel_mask) <= FCC_2) && reqFormat == config->format && config->format == AUDIO_FORMAT_PCM_16_BIT && (config->sample_rate <= 2 * reqSamplingRate) && (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_2) && (audio_channel_count_from_in_mask(reqChannelMask) <= FCC_2)) { // FIXME describe the change proposed by HAL (save old values so we can log them here) ALOGV("openInput() reopening with proposed sampling rate and channel mask"); inStream = NULL; status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, &inStream, flags); status = inHwHal->open_input_stream(inHwHal, id, device, config, &inStream, flags); // FIXME log this new status; HAL should not propose any further changes } Loading Loading @@ -1931,30 +1987,18 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, // Start record thread // RecordThread requires both input and output device indication to forward to audio // pre processing modules RecordThread *thread = new RecordThread(this, sp<RecordThread> thread = new RecordThread(this, input, id, primaryOutputDevice_l(), *pDevices device #ifdef TEE_SINK , teeSink #endif ); mRecordThreads.add(id, thread); ALOGV("openInput() created record thread: ID %d thread %p", id, thread); if (pSamplingRate != NULL) { *pSamplingRate = reqSamplingRate; } if (pFormat != NULL) { *pFormat = config.format; } if (pChannelMask != NULL) { *pChannelMask = reqChannelMask; } // notify client processes of the new input creation thread->audioConfigChanged(AudioSystem::INPUT_OPENED); return id; ALOGV("openInput() created record thread: ID %d thread %p", id, thread.get()); return thread; } return 0; Loading @@ -1981,17 +2025,26 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input) audioConfigChanged(AudioSystem::INPUT_CLOSED, input, NULL); mRecordThreads.removeItem(input); } thread->exit(); // The thread entity (active unit of execution) is no longer running here, // but the ThreadBase container still exists. // FIXME: calling thread->exit() without mLock held should not be needed anymore now that // we have a different lock for notification client closeInputFinish(thread); return NO_ERROR; } void AudioFlinger::closeInputFinish(sp<RecordThread> thread) { thread->exit(); AudioStreamIn *in = thread->clearInput(); ALOG_ASSERT(in != NULL, "in shouldn't be NULL"); // from now on thread->mInput is NULL in->hwDev()->close_input_stream(in->hwDev(), in->stream); delete in; } return NO_ERROR; void AudioFlinger::closeInputInternal_l(sp<RecordThread> thread) { mRecordThreads.removeItem(thread->mId); closeInputFinish(thread); } status_t AudioFlinger::invalidateStream(audio_stream_type_t stream) Loading
services/audioflinger/AudioFlinger.h +19 −2 Original line number Diff line number Diff line Loading @@ -489,6 +489,18 @@ private: PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const; MixerThread *checkMixerThread_l(audio_io_handle_t output) const; RecordThread *checkRecordThread_l(audio_io_handle_t input) const; sp<RecordThread> openInput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_input_flags_t flags); sp<PlaybackThread> openOutput_l(audio_module_handle_t module, audio_devices_t device, struct audio_config *config, audio_output_flags_t flags); void closeOutputFinish(sp<PlaybackThread> thread); void closeInputFinish(sp<RecordThread> thread); // no range check, AudioFlinger::mLock held bool streamMute_l(audio_stream_type_t stream) const { return mStreamTypes[stream].mute; } Loading Loading @@ -530,10 +542,11 @@ private: AHWD_CAN_SET_MASTER_MUTE = 0x2, }; AudioHwDevice(const char *moduleName, AudioHwDevice(audio_module_handle_t handle, const char *moduleName, audio_hw_device_t *hwDevice, Flags flags) : mModuleName(strdup(moduleName)) : mHandle(handle), mModuleName(strdup(moduleName)) , mHwDevice(hwDevice) , mFlags(flags) { } /*virtual*/ ~AudioHwDevice() { free((void *)mModuleName); } Loading @@ -546,11 +559,13 @@ private: return (0 != (mFlags & AHWD_CAN_SET_MASTER_MUTE)); } audio_module_handle_t handle() const { return mHandle; } const char *moduleName() const { return mModuleName; } audio_hw_device_t *hwDevice() const { return mHwDevice; } uint32_t version() const { return mHwDevice->common.version; } private: audio_module_handle_t mHandle; const char * const mModuleName; audio_hw_device_t * const mHwDevice; const Flags mFlags; Loading Loading @@ -669,7 +684,9 @@ private: // for use from destructor status_t closeOutput_nonvirtual(audio_io_handle_t output); void closeOutputInternal_l(sp<PlaybackThread> thread); status_t closeInput_nonvirtual(audio_io_handle_t input); void closeInputInternal_l(sp<RecordThread> thread); #ifdef TEE_SINK // all record threads serially share a common tee sink, which is re-created on format change Loading
services/audioflinger/PatchPanel.cpp +288 −64 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/audioflinger/PatchPanel.h +24 −6 Original line number Diff line number Diff line Loading @@ -21,6 +21,9 @@ class PatchPanel : public RefBase { public: class Patch; PatchPanel(const sp<AudioFlinger>& audioFlinger); virtual ~PatchPanel(); Loading @@ -45,15 +48,30 @@ public: /* Set audio port configuration */ status_t setAudioPortConfig(const struct audio_port_config *config); status_t createPatchConnections(Patch *patch, const struct audio_patch *audioPatch); void clearPatchConnections(Patch *patch); class Patch { public: Patch(const struct audio_patch *patch) : mAudioPatch(*patch), mHandle(0), mHalHandle(0) {} mAudioPatch(*patch), mHandle(AUDIO_PATCH_HANDLE_NONE), mHalHandle(AUDIO_PATCH_HANDLE_NONE), mRecordPatchHandle(AUDIO_PATCH_HANDLE_NONE), mPlaybackPatchHandle(AUDIO_PATCH_HANDLE_NONE) {} ~Patch() {} struct audio_patch mAudioPatch; audio_patch_handle_t mHandle; audio_patch_handle_t mHalHandle; sp<PlaybackThread> mPlaybackThread; sp<PlaybackThread::PatchTrack> mPatchTrack; sp<RecordThread> mRecordThread; sp<RecordThread::PatchRecord> mPatchRecord; audio_patch_handle_t mRecordPatchHandle; audio_patch_handle_t mPlaybackPatchHandle; }; private: const wp<AudioFlinger> mAudioFlinger; SortedVector <Patch *> mPatches; Loading