Loading media/libaudioclient/AudioRecord.cpp +55 −25 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ AudioRecord::~AudioRecord() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput); } IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); Loading Loading @@ -499,19 +499,26 @@ audio_port_handle_t AudioRecord::getInputDevice() { return mSelectedDeviceId; } audio_port_handle_t AudioRecord::getRoutedDeviceId() { AutoMutex lock(mLock); if (mInput == AUDIO_IO_HANDLE_NONE) { return AUDIO_PORT_HANDLE_NONE; // must be called with mLock held void AudioRecord::updateRoutedDeviceId_l() { // if the record is inactive, do not update actual device as the input stream maybe routed // from a device not relevant to this client because of other active use cases. if (!mActive) { return; } // if the input stream does not have an active audio patch, use either the device initially // selected by audio policy manager or the last routed device if (mInput != AUDIO_IO_HANDLE_NONE) { audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput); if (deviceId == AUDIO_PORT_HANDLE_NONE) { deviceId = mRoutedDeviceId; } if (deviceId != AUDIO_PORT_HANDLE_NONE) { mRoutedDeviceId = deviceId; return deviceId; } } } audio_port_handle_t AudioRecord::getRoutedDeviceId() { AutoMutex lock(mLock); updateRoutedDeviceId_l(); return mRoutedDeviceId; } // ------------------------------------------------------------------------- Loading @@ -537,9 +544,6 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 return NO_INIT; } if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); } audio_io_handle_t input; // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted. Loading Loading @@ -744,6 +748,15 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 } mNotificationFramesAct = (uint32_t) notificationFrames; //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mInput != input) { if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); } AudioSystem::addAudioDeviceCallback(this, input); } // We retain a copy of the I/O handle, but don't own the reference mInput = input; mRefreshRemaining = true; Loading @@ -763,10 +776,6 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); if (mDeviceCallback != 0) { AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput); } return NO_ERROR; // End of retry loop. Loading Loading @@ -1239,7 +1248,7 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback == callback) { if (mDeviceCallback.unsafe_get() == callback.get()) { ALOGW("%s adding same callback!", __FUNCTION__); return INVALID_OPERATION; } Loading @@ -1247,9 +1256,9 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa if (mInput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s callback already present!", __FUNCTION__); AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput); } status = AudioSystem::addAudioDeviceCallback(callback, mInput); status = AudioSystem::addAudioDeviceCallback(this, mInput); } mDeviceCallback = callback; return status; Loading @@ -1263,17 +1272,38 @@ status_t AudioRecord::removeAudioDeviceCallback( return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback != callback) { if (mDeviceCallback.unsafe_get() != callback.get()) { ALOGW("%s removing different callback!", __FUNCTION__); return INVALID_OPERATION; } mDeviceCallback.clear(); if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput); } mDeviceCallback = 0; return NO_ERROR; } void AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId) { sp<AudioSystem::AudioDeviceCallback> callback; { AutoMutex lock(mLock); if (audioIo != mInput) { return; } callback = mDeviceCallback.promote(); // only update device if the record is active as route changes due to other use cases are // irrelevant for this client if (mActive) { mRoutedDeviceId = deviceId; } } if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId); } } // ========================================================================= void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused) Loading media/libaudioclient/AudioSystem.cpp +39 −17 Original line number Diff line number Diff line Loading @@ -493,14 +493,16 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return; audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE; Vector < sp<AudioDeviceCallback> > callbacks; Vector < wp<AudioDeviceCallback> > callbacks; { Mutex::Autolock _l(mLock); switch (event) { case AUDIO_OUTPUT_OPENED: case AUDIO_INPUT_OPENED: { case AUDIO_OUTPUT_REGISTERED: case AUDIO_INPUT_OPENED: case AUDIO_INPUT_REGISTERED: { sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle); if (oldDesc == 0) { mIoDescriptors.add(ioDesc->mIoHandle, ioDesc); Loading @@ -511,13 +513,19 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) { deviceId = ioDesc->getDeviceId(); if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) { ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle); if (ioIndex >= 0) { callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); } } ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x " "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED ? "output" : "input", } ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x " "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED || event == AUDIO_OUTPUT_REGISTERED ? "output" : "input", event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED ? "opened" : "registered", ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->getDeviceId()); } break; Loading Loading @@ -563,9 +571,23 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even } break; } } bool callbackRemoved = false; // callbacks.size() != 0 => ioDesc->mIoHandle and deviceId are valid for (size_t i = 0; i < callbacks.size(); i++) { callbacks[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); for (size_t i = 0; i < callbacks.size(); ) { sp<AudioDeviceCallback> callback = callbacks[i].promote(); if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); i++; } else { callbacks.removeAt(i); callbackRemoved = true; } } // clean up callback list while we are here if some clients have disappeared without // unregistering their callback if (callbackRemoved) { Mutex::Autolock _l(mLock); mAudioDeviceCallbacks.replaceValueFor(ioDesc->mIoHandle, callbacks); } } Loading Loading @@ -618,17 +640,17 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_ } status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { Mutex::Autolock _l(mLock); Vector < sp<AudioDeviceCallback> > callbacks; Vector < wp<AudioDeviceCallback> > callbacks; ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo); if (ioIndex >= 0) { callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); } for (size_t cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) { if (callbacks[cbIndex] == callback) { if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) { return INVALID_OPERATION; } } Loading @@ -639,18 +661,18 @@ status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback( } status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { Mutex::Autolock _l(mLock); ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo); if (ioIndex < 0) { return INVALID_OPERATION; } Vector < sp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); Vector < wp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); size_t cbIndex; for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) { if (callbacks[cbIndex] == callback) { if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) { break; } } Loading Loading @@ -1128,7 +1150,7 @@ status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callb } status_t AudioSystem::addAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { Loading @@ -1145,7 +1167,7 @@ status_t AudioSystem::addAudioDeviceCallback( } status_t AudioSystem::removeAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { Loading media/libaudioclient/AudioTrack.cpp +67 −28 Original line number Diff line number Diff line Loading @@ -278,7 +278,7 @@ AudioTrack::~AudioTrack() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput); } IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); Loading Loading @@ -1231,19 +1231,26 @@ audio_port_handle_t AudioTrack::getOutputDevice() { return mSelectedDeviceId; } audio_port_handle_t AudioTrack::getRoutedDeviceId() { AutoMutex lock(mLock); if (mOutput == AUDIO_IO_HANDLE_NONE) { return AUDIO_PORT_HANDLE_NONE; // must be called with mLock held void AudioTrack::updateRoutedDeviceId_l() { // if the track is inactive, do not update actual device as the output stream maybe routed // to a device not relevant to this client because of other active use cases. if (mState != STATE_ACTIVE) { return; } // if the output stream does not have an active audio patch, use either the device initially // selected by audio policy manager or the last routed device if (mOutput != AUDIO_IO_HANDLE_NONE) { audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mOutput); if (deviceId == AUDIO_PORT_HANDLE_NONE) { deviceId = mRoutedDeviceId; } if (deviceId != AUDIO_PORT_HANDLE_NONE) { mRoutedDeviceId = deviceId; return deviceId; } } } audio_port_handle_t AudioTrack::getRoutedDeviceId() { AutoMutex lock(mLock); updateRoutedDeviceId_l(); return mRoutedDeviceId; } status_t AudioTrack::attachAuxEffect(int effectId) Loading Loading @@ -1307,12 +1314,10 @@ status_t AudioTrack::createTrack_l() return NO_INIT; } if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); } audio_io_handle_t output; audio_stream_type_t streamType = mStreamType; audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL; bool callbackAdded = false; // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted. // After fast request is denied, we will request again if IAudioTrack is re-created. Loading Loading @@ -1517,12 +1522,14 @@ status_t AudioTrack::createTrack_l() sp<IMemory> iMem = track->getCblk(); if (iMem == 0) { ALOGE("Could not get control block"); return NO_INIT; status = NO_INIT; goto release; } void *iMemPointer = iMem->pointer(); if (iMemPointer == NULL) { ALOGE("Could not get control block pointer"); return NO_INIT; status = NO_INIT; goto release; } // invariant that mAudioTrack != 0 is true only after set() returns successfully if (mAudioTrack != 0) { Loading Loading @@ -1584,6 +1591,15 @@ status_t AudioTrack::createTrack_l() } } //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mOutput != output) { if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mOutput); } AudioSystem::addAudioDeviceCallback(this, output); callbackAdded = true; } // We retain a copy of the I/O handle, but don't own the reference mOutput = output; mRefreshRemaining = true; Loading @@ -1599,7 +1615,8 @@ status_t AudioTrack::createTrack_l() buffers = mSharedBuffer->pointer(); if (buffers == NULL) { ALOGE("Could not get buffer pointer"); return NO_INIT; status = NO_INIT; goto release; } } Loading Loading @@ -1644,15 +1661,15 @@ status_t AudioTrack::createTrack_l() mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this); if (mDeviceCallback != 0) { AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput); } return NO_ERROR; } release: AudioSystem::releaseOutput(output, streamType, mSessionId); if (callbackAdded) { // note: mOutput is always valid is callbackAdded is true AudioSystem::removeAudioDeviceCallback(this, mOutput); } if (status == NO_ERROR) { status = NO_INIT; } Loading Loading @@ -2853,7 +2870,7 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback == callback) { if (mDeviceCallback.unsafe_get() == callback.get()) { ALOGW("%s adding same callback!", __FUNCTION__); return INVALID_OPERATION; } Loading @@ -2861,9 +2878,9 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal if (mOutput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s callback already present!", __FUNCTION__); AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput); } status = AudioSystem::addAudioDeviceCallback(callback, mOutput); status = AudioSystem::addAudioDeviceCallback(this, mOutput); } mDeviceCallback = callback; return status; Loading @@ -2877,17 +2894,39 @@ status_t AudioTrack::removeAudioDeviceCallback( return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback != callback) { if (mDeviceCallback.unsafe_get() != callback.get()) { ALOGW("%s removing different callback!", __FUNCTION__); return INVALID_OPERATION; } mDeviceCallback.clear(); if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput); } mDeviceCallback = 0; return NO_ERROR; } void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId) { sp<AudioSystem::AudioDeviceCallback> callback; { AutoMutex lock(mLock); if (audioIo != mOutput) { return; } callback = mDeviceCallback.promote(); // only update device if the track is active as route changes due to other use cases are // irrelevant for this client if (mState == STATE_ACTIVE) { mRoutedDeviceId = deviceId; } } if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId); } } status_t AudioTrack::pendingDuration(int32_t *msec, ExtendedTimestamp::Location location) { if (msec == nullptr || Loading media/libaudioclient/include/media/AudioIoDescriptor.h +2 −0 Original line number Diff line number Diff line Loading @@ -20,9 +20,11 @@ namespace android { enum audio_io_config_event { AUDIO_OUTPUT_REGISTERED, AUDIO_OUTPUT_OPENED, AUDIO_OUTPUT_CLOSED, AUDIO_OUTPUT_CONFIG_CHANGED, AUDIO_INPUT_REGISTERED, AUDIO_INPUT_OPENED, AUDIO_INPUT_CLOSED, AUDIO_INPUT_CONFIG_CHANGED, Loading media/libaudioclient/include/media/AudioRecord.h +14 −3 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ class AudioRecordClientProxy; // ---------------------------------------------------------------------------- class AudioRecord : public RefBase class AudioRecord : public AudioSystem::AudioDeviceCallback { public: Loading Loading @@ -427,7 +427,12 @@ public: /* Returns the ID of the audio device actually used by the input to which this AudioRecord * is attached. * A value of AUDIO_PORT_HANDLE_NONE indicates the AudioRecord is not attached to any input. * The device ID is relevant only if the AudioRecord is active. * When the AudioRecord is inactive, the device ID returned can be either: * - AUDIO_PORT_HANDLE_NONE if the AudioRecord is not attached to any output. * - The device ID used before paused or stopped. * - The device ID selected by audio policy manager of setOutputDevice() if the AudioRecord * has not been started yet. * * Parameters: * none. Loading Loading @@ -457,6 +462,10 @@ public: status_t removeAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback); // AudioSystem::AudioDeviceCallback> virtuals virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId); private: /* If nonContig is non-NULL, it is an output parameter that will be set to the number of * additional non-contiguous frames that are predicted to be available immediately, Loading Loading @@ -564,6 +573,8 @@ private: // FIXME enum is faster than strcmp() for parameter 'from' status_t restoreRecord_l(const char *from); void updateRoutedDeviceId_l(); sp<AudioRecordThread> mAudioRecordThread; mutable Mutex mLock; Loading Loading @@ -668,7 +679,7 @@ private: audio_port_handle_t mRoutedDeviceId; // Device actually selected by audio policy manager: // May not match the app selection depending on other // activity and connected devices sp<AudioSystem::AudioDeviceCallback> mDeviceCallback; wp<AudioSystem::AudioDeviceCallback> mDeviceCallback; audio_port_handle_t mPortId; // unique ID allocated by audio policy }; Loading Loading
media/libaudioclient/AudioRecord.cpp +55 −25 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ AudioRecord::~AudioRecord() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput); } IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); Loading Loading @@ -499,19 +499,26 @@ audio_port_handle_t AudioRecord::getInputDevice() { return mSelectedDeviceId; } audio_port_handle_t AudioRecord::getRoutedDeviceId() { AutoMutex lock(mLock); if (mInput == AUDIO_IO_HANDLE_NONE) { return AUDIO_PORT_HANDLE_NONE; // must be called with mLock held void AudioRecord::updateRoutedDeviceId_l() { // if the record is inactive, do not update actual device as the input stream maybe routed // from a device not relevant to this client because of other active use cases. if (!mActive) { return; } // if the input stream does not have an active audio patch, use either the device initially // selected by audio policy manager or the last routed device if (mInput != AUDIO_IO_HANDLE_NONE) { audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput); if (deviceId == AUDIO_PORT_HANDLE_NONE) { deviceId = mRoutedDeviceId; } if (deviceId != AUDIO_PORT_HANDLE_NONE) { mRoutedDeviceId = deviceId; return deviceId; } } } audio_port_handle_t AudioRecord::getRoutedDeviceId() { AutoMutex lock(mLock); updateRoutedDeviceId_l(); return mRoutedDeviceId; } // ------------------------------------------------------------------------- Loading @@ -537,9 +544,6 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 return NO_INIT; } if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); } audio_io_handle_t input; // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted. Loading Loading @@ -744,6 +748,15 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 } mNotificationFramesAct = (uint32_t) notificationFrames; //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mInput != input) { if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); } AudioSystem::addAudioDeviceCallback(this, input); } // We retain a copy of the I/O handle, but don't own the reference mInput = input; mRefreshRemaining = true; Loading @@ -763,10 +776,6 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16 mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); if (mDeviceCallback != 0) { AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput); } return NO_ERROR; // End of retry loop. Loading Loading @@ -1239,7 +1248,7 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback == callback) { if (mDeviceCallback.unsafe_get() == callback.get()) { ALOGW("%s adding same callback!", __FUNCTION__); return INVALID_OPERATION; } Loading @@ -1247,9 +1256,9 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa if (mInput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s callback already present!", __FUNCTION__); AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput); } status = AudioSystem::addAudioDeviceCallback(callback, mInput); status = AudioSystem::addAudioDeviceCallback(this, mInput); } mDeviceCallback = callback; return status; Loading @@ -1263,17 +1272,38 @@ status_t AudioRecord::removeAudioDeviceCallback( return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback != callback) { if (mDeviceCallback.unsafe_get() != callback.get()) { ALOGW("%s removing different callback!", __FUNCTION__); return INVALID_OPERATION; } mDeviceCallback.clear(); if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput); } mDeviceCallback = 0; return NO_ERROR; } void AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId) { sp<AudioSystem::AudioDeviceCallback> callback; { AutoMutex lock(mLock); if (audioIo != mInput) { return; } callback = mDeviceCallback.promote(); // only update device if the record is active as route changes due to other use cases are // irrelevant for this client if (mActive) { mRoutedDeviceId = deviceId; } } if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId); } } // ========================================================================= void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused) Loading
media/libaudioclient/AudioSystem.cpp +39 −17 Original line number Diff line number Diff line Loading @@ -493,14 +493,16 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return; audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE; Vector < sp<AudioDeviceCallback> > callbacks; Vector < wp<AudioDeviceCallback> > callbacks; { Mutex::Autolock _l(mLock); switch (event) { case AUDIO_OUTPUT_OPENED: case AUDIO_INPUT_OPENED: { case AUDIO_OUTPUT_REGISTERED: case AUDIO_INPUT_OPENED: case AUDIO_INPUT_REGISTERED: { sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle); if (oldDesc == 0) { mIoDescriptors.add(ioDesc->mIoHandle, ioDesc); Loading @@ -511,13 +513,19 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) { deviceId = ioDesc->getDeviceId(); if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) { ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle); if (ioIndex >= 0) { callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); } } ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x " "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED ? "output" : "input", } ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x " "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED || event == AUDIO_OUTPUT_REGISTERED ? "output" : "input", event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED ? "opened" : "registered", ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->getDeviceId()); } break; Loading Loading @@ -563,9 +571,23 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even } break; } } bool callbackRemoved = false; // callbacks.size() != 0 => ioDesc->mIoHandle and deviceId are valid for (size_t i = 0; i < callbacks.size(); i++) { callbacks[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); for (size_t i = 0; i < callbacks.size(); ) { sp<AudioDeviceCallback> callback = callbacks[i].promote(); if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); i++; } else { callbacks.removeAt(i); callbackRemoved = true; } } // clean up callback list while we are here if some clients have disappeared without // unregistering their callback if (callbackRemoved) { Mutex::Autolock _l(mLock); mAudioDeviceCallbacks.replaceValueFor(ioDesc->mIoHandle, callbacks); } } Loading Loading @@ -618,17 +640,17 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_ } status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { Mutex::Autolock _l(mLock); Vector < sp<AudioDeviceCallback> > callbacks; Vector < wp<AudioDeviceCallback> > callbacks; ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo); if (ioIndex >= 0) { callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); } for (size_t cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) { if (callbacks[cbIndex] == callback) { if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) { return INVALID_OPERATION; } } Loading @@ -639,18 +661,18 @@ status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback( } status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { Mutex::Autolock _l(mLock); ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo); if (ioIndex < 0) { return INVALID_OPERATION; } Vector < sp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); Vector < wp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); size_t cbIndex; for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) { if (callbacks[cbIndex] == callback) { if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) { break; } } Loading Loading @@ -1128,7 +1150,7 @@ status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callb } status_t AudioSystem::addAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { Loading @@ -1145,7 +1167,7 @@ status_t AudioSystem::addAudioDeviceCallback( } status_t AudioSystem::removeAudioDeviceCallback( const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { Loading
media/libaudioclient/AudioTrack.cpp +67 −28 Original line number Diff line number Diff line Loading @@ -278,7 +278,7 @@ AudioTrack::~AudioTrack() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput); } IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); Loading Loading @@ -1231,19 +1231,26 @@ audio_port_handle_t AudioTrack::getOutputDevice() { return mSelectedDeviceId; } audio_port_handle_t AudioTrack::getRoutedDeviceId() { AutoMutex lock(mLock); if (mOutput == AUDIO_IO_HANDLE_NONE) { return AUDIO_PORT_HANDLE_NONE; // must be called with mLock held void AudioTrack::updateRoutedDeviceId_l() { // if the track is inactive, do not update actual device as the output stream maybe routed // to a device not relevant to this client because of other active use cases. if (mState != STATE_ACTIVE) { return; } // if the output stream does not have an active audio patch, use either the device initially // selected by audio policy manager or the last routed device if (mOutput != AUDIO_IO_HANDLE_NONE) { audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mOutput); if (deviceId == AUDIO_PORT_HANDLE_NONE) { deviceId = mRoutedDeviceId; } if (deviceId != AUDIO_PORT_HANDLE_NONE) { mRoutedDeviceId = deviceId; return deviceId; } } } audio_port_handle_t AudioTrack::getRoutedDeviceId() { AutoMutex lock(mLock); updateRoutedDeviceId_l(); return mRoutedDeviceId; } status_t AudioTrack::attachAuxEffect(int effectId) Loading Loading @@ -1307,12 +1314,10 @@ status_t AudioTrack::createTrack_l() return NO_INIT; } if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); } audio_io_handle_t output; audio_stream_type_t streamType = mStreamType; audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL; bool callbackAdded = false; // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted. // After fast request is denied, we will request again if IAudioTrack is re-created. Loading Loading @@ -1517,12 +1522,14 @@ status_t AudioTrack::createTrack_l() sp<IMemory> iMem = track->getCblk(); if (iMem == 0) { ALOGE("Could not get control block"); return NO_INIT; status = NO_INIT; goto release; } void *iMemPointer = iMem->pointer(); if (iMemPointer == NULL) { ALOGE("Could not get control block pointer"); return NO_INIT; status = NO_INIT; goto release; } // invariant that mAudioTrack != 0 is true only after set() returns successfully if (mAudioTrack != 0) { Loading Loading @@ -1584,6 +1591,15 @@ status_t AudioTrack::createTrack_l() } } //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mOutput != output) { if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mOutput); } AudioSystem::addAudioDeviceCallback(this, output); callbackAdded = true; } // We retain a copy of the I/O handle, but don't own the reference mOutput = output; mRefreshRemaining = true; Loading @@ -1599,7 +1615,8 @@ status_t AudioTrack::createTrack_l() buffers = mSharedBuffer->pointer(); if (buffers == NULL) { ALOGE("Could not get buffer pointer"); return NO_INIT; status = NO_INIT; goto release; } } Loading Loading @@ -1644,15 +1661,15 @@ status_t AudioTrack::createTrack_l() mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this); if (mDeviceCallback != 0) { AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput); } return NO_ERROR; } release: AudioSystem::releaseOutput(output, streamType, mSessionId); if (callbackAdded) { // note: mOutput is always valid is callbackAdded is true AudioSystem::removeAudioDeviceCallback(this, mOutput); } if (status == NO_ERROR) { status = NO_INIT; } Loading Loading @@ -2853,7 +2870,7 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback == callback) { if (mDeviceCallback.unsafe_get() == callback.get()) { ALOGW("%s adding same callback!", __FUNCTION__); return INVALID_OPERATION; } Loading @@ -2861,9 +2878,9 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal if (mOutput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s callback already present!", __FUNCTION__); AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput); } status = AudioSystem::addAudioDeviceCallback(callback, mOutput); status = AudioSystem::addAudioDeviceCallback(this, mOutput); } mDeviceCallback = callback; return status; Loading @@ -2877,17 +2894,39 @@ status_t AudioTrack::removeAudioDeviceCallback( return BAD_VALUE; } AutoMutex lock(mLock); if (mDeviceCallback != callback) { if (mDeviceCallback.unsafe_get() != callback.get()) { ALOGW("%s removing different callback!", __FUNCTION__); return INVALID_OPERATION; } mDeviceCallback.clear(); if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput); } mDeviceCallback = 0; return NO_ERROR; } void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId) { sp<AudioSystem::AudioDeviceCallback> callback; { AutoMutex lock(mLock); if (audioIo != mOutput) { return; } callback = mDeviceCallback.promote(); // only update device if the track is active as route changes due to other use cases are // irrelevant for this client if (mState == STATE_ACTIVE) { mRoutedDeviceId = deviceId; } } if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId); } } status_t AudioTrack::pendingDuration(int32_t *msec, ExtendedTimestamp::Location location) { if (msec == nullptr || Loading
media/libaudioclient/include/media/AudioIoDescriptor.h +2 −0 Original line number Diff line number Diff line Loading @@ -20,9 +20,11 @@ namespace android { enum audio_io_config_event { AUDIO_OUTPUT_REGISTERED, AUDIO_OUTPUT_OPENED, AUDIO_OUTPUT_CLOSED, AUDIO_OUTPUT_CONFIG_CHANGED, AUDIO_INPUT_REGISTERED, AUDIO_INPUT_OPENED, AUDIO_INPUT_CLOSED, AUDIO_INPUT_CONFIG_CHANGED, Loading
media/libaudioclient/include/media/AudioRecord.h +14 −3 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ class AudioRecordClientProxy; // ---------------------------------------------------------------------------- class AudioRecord : public RefBase class AudioRecord : public AudioSystem::AudioDeviceCallback { public: Loading Loading @@ -427,7 +427,12 @@ public: /* Returns the ID of the audio device actually used by the input to which this AudioRecord * is attached. * A value of AUDIO_PORT_HANDLE_NONE indicates the AudioRecord is not attached to any input. * The device ID is relevant only if the AudioRecord is active. * When the AudioRecord is inactive, the device ID returned can be either: * - AUDIO_PORT_HANDLE_NONE if the AudioRecord is not attached to any output. * - The device ID used before paused or stopped. * - The device ID selected by audio policy manager of setOutputDevice() if the AudioRecord * has not been started yet. * * Parameters: * none. Loading Loading @@ -457,6 +462,10 @@ public: status_t removeAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback); // AudioSystem::AudioDeviceCallback> virtuals virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId); private: /* If nonContig is non-NULL, it is an output parameter that will be set to the number of * additional non-contiguous frames that are predicted to be available immediately, Loading Loading @@ -564,6 +573,8 @@ private: // FIXME enum is faster than strcmp() for parameter 'from' status_t restoreRecord_l(const char *from); void updateRoutedDeviceId_l(); sp<AudioRecordThread> mAudioRecordThread; mutable Mutex mLock; Loading Loading @@ -668,7 +679,7 @@ private: audio_port_handle_t mRoutedDeviceId; // Device actually selected by audio policy manager: // May not match the app selection depending on other // activity and connected devices sp<AudioSystem::AudioDeviceCallback> mDeviceCallback; wp<AudioSystem::AudioDeviceCallback> mDeviceCallback; audio_port_handle_t mPortId; // unique ID allocated by audio policy }; Loading